diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index 0d0f78b41..000000000 --- a/ChangeLog +++ /dev/null @@ -1,309 +0,0 @@ -Deluge 0.5.9.2 (19 June 2008) - * Add abilitity to move to a different partition - * Add option to send redundant haves (show peers our progress) - * Add 'add url' from tray - * Fix uploaded_memory from reverting to state value when doing a forced recheck - * Fixed 64-bit overflow issues - * Fixed total_wanted issue for files > 2 GB - * Fixed entry and scrape bug - * Fixed issue with torrents with 0 pieces - * Fixed possible unicode problems - * Fixed minimum reconnect time bug - -Deluge 0.5.9.1 (19 May 2008) - * Fix queue reordering on startup - * Fix open folder - * Fix advanced progress bar when only 1 piece in torrent - * Fix to prevent an invalid torrent file from crashing Deluge - -Deluge 0.5.9.0 (30 April 2008) - * Fix ratio - * Fix opening folers/files on windows - * Move all packages to use Python 2.5 - -Deluge 0.5.8.9 (14 April 2008) - * Fix segfault caused in 0.5.8.8 when adding torrents - * Change fast resume to use is_finished - * LT - Fix private flag - * LT - Verify url before connection to web seed - -Deluge 0.5.8.8 (08 April 2008) - * Fix ubuntu hardy bug sine they've renamed and broken up the packages. - * Fix ratio (again) - * Sync with asio 1.0 release - * Remove file manager from preferences - * Sync with libtorrent 0.13 release - * Fix for vista dbus not closing bug - -Deluge 0.5.8.7 (25 March 2008) - * UPnP fixes - * Bandwidth limiter fix - * Various DHT fixes - * Fix upload ratio not saving - * Fix WebUI crash (ticket #89) - * Clear seeding torrents now deletes the ".torrent" file - * Fix keyboard scrolling of plugins - * Scheduler can now handle number of active torrents, upload slots and max connections - Ben - -Deluge 0.5.8.6 (11 March 2008) - * Fix fast-resume deletion on shutdown - * Tweak saving of uploaded memory (more effective ratio) - * Add torrents with .fastresume files before torrents that don't - * Fix a UI hang (bug #72) - -Deluge 0.5.8.5 (28 February 2008) - * Fix force recheck - * Auto scraping of tracker if it doesn't report number of peers on reply - * Fix web seed proxy preference - * Fix adding of duplicate torrents - * Fix timers for saving fastresume and uploaded memory - * Fix rechecking on start - * UPnP fixes - * Fix possible libtorrent crash in storage - -Deluge 0.5.8.4 (14 February 2008) - * Randomize encryption pad size to evade throttling - * https support - * Add "seed time" to preferences - * Add switch torrent source to "Move Torrent" plugin - * Fix alignment of torrent info - * Fix possible hang with torrents with many pieces - * Don't resave fast-resume for seeding torrents - * Add logout to WebUI - * Only draw the advanced progress bar if 'num_pieces' is greater than 0 - prevents crash - -Deluge 0.5.8.3 (28 January 2008) - * Fix remote exploit which could crash Deluge - * Fix high cpu spikes - * Fix torrent order between sessions - * Fix loading of BlocklistImport plugin - -Deluge 0.5.8.2 (24 January 2008) - * Fix column width saving - * Option to download new blocklist after certain number of days - Patch from Mark Stahler - * Fix ui-locking when tracker responded in non-utf8 encoding - * Remove Extra Stats plugin - * Prevent Scheduler plugin from setting an invalid 'max_active_torrents' - -Deluge 0.5.8.1 (18 January 2008) - * Catch various exceptions from possibly corrupted persistent.state - * Use pieces wanted instead of total pieces to draw adv progress bar - * Properly catch 'address already in use' error when trying to use a port that is in use - * Attempt to fix issue where all the columns start very small - * Change how we handle fastresume - should prevent rechecking - * New theme for windows - * Performance enhancements by removing needless casts - * Search is now a plugin - * Browser removed - -Deluge 0.5.8 (29 December 2007) - * Fix handling of corrupt torrent files - * Fix having two instances of Deluge running on Ubuntu - -Deluge 0.5.8RC2 (25 December 2007) - * Change add torrent to ctrl+n - * Change notification plugin to not show the file list, but only the torrent - name - * Allow removal of browser icon from toolbar - * Add buttons to browser to launch the main and footer frames into an - external browser - * Fix removing torrents from deluge template of webui - vonck7 - * Set the advanced webui template as default - * Cut down significantly on the memory usage of the blocklist plugin - * Fix some UPnP bugs - * Fix "New version" alert from freezing sometimes - * Prioritizes local peers over non-local ones when finding connect - * Wish everyone a happy holiday :) - - -Deluge 0.5.8RC1 (22 December 2007) - * Key bindings: - ctrl+a adds a torrent - ctrl+l adds a torrent via URL - ctrl+p pauses torrent(s) - ctrl+r resumes torrent(s) - delete removes torrent(s) - * Fix total uploaded display bug - * Fix seeding ratio stop on finished torrents - * Fix zombie processes from occurring - * Fix saying goodbye to trackers - * Increase auto remove ratio to 100 - * Fix problem on Windows with filenames that have special characters - * Fix saving of which columns to show - * Fix init script error on exotic systems - * Add web seed to Torrent Creator plugin - * TorrentSearch is now built-in - * Add internal anonymizing browser - Key bindings for that are as follows: - ctrl+l focus on location bar - ctrl+k focus on search bar - ctrl+r refreshes current page - ctrl+enter adds 'www.' and '.com' to url string - shift+enter adds 'www.' and '.net' to url string - -Deluge 0.5.7.1 (01 December 2007) - * Tweak full hd warning so that it only displays itself once per torrent that - it has to pause. - * Fixed crash and corruption of persistent.state while adding a duplicate - torrent. Also caused yet another invalid handle error. - * Increase tracker timeout - -Deluge 0.5.7 (26 November 2007) - * Scrape support - * Manual force-recheck - * Add local peer discovery (aka local service discovery) - * Blocklist plugin will now display errors, instead of just crashing on a bad - list or wrong type - * Add torrent in paused state option - * Add advanced progress bar - * Fix bug in merging trackers - * Various updates to WebUI, including https support and advanced template by vonck7 - * Add maximum connection attempts per second preference - * Fix bug where loaded plugins were forgotten if Deluge crashed - * Fix ratio bugs (hopefully for the last time) - * Add preference to only show file selection popup if torrent has multiple files - * Fix pause all and resume all bugs - * Fix client not loading if our website goes down (new version check failing) - * Allow torrent creation with no trackers - * Scheduler plugin revamp by Ben Klein - * Fix ETA from going backwards - * UI warning on full HD - no longer just silently pauses torrents - * Replace SimpleRSS with FlexRSS - * Add preference for the location of torrent files - * Add autoload folder - * Copy translator credits from Launchpad to our about->credits - * Differentiate between queued and paused torrents. Able to pause queued - torrents - patch by yobbobandana - * Show error when writing/permission problems occur - -Deluge 0.5.6.2 (31 October 2007) - * Set default piece size to 256-KiB in TorrentCreator plugin and add 2048KiB - as a size option. - * Fix a bug in Debian package that caused the UI to completely freeze when a - torrent finished - * Find and fix another shutdown bug that mostly Gutsy users were encountering - * Fix a couple of WebUI bugs, including the "index" page erroring out - -Deluge 0.5.6.1 (28 October 2007) - * Fix invalid handle error - * Fix shutdown hang - -Deluge 0.5.6 (24 October 2007) - * Web Interface Plugin - * Hopefully fix "losing data" and having to re-download parts (for real this time :p) - * Use new full allocation method which does not create files until one of its - pieces is downloaded - * Tray lock password is no longer stored in plain text - * Update the Scheduler plugin and fix a bunch of bugs on it - * Double-clicking on a torrent opens up its containing folder - * Fix SpeedLimiter plugin when setting upload limits - * Fix MoveTorrent plugin when moving actively downloading torrents - * Pause torrents while importing blocklist and resume them when finished - * Remove TorrentPieces and disable its use - * A whole bunch of stuff for Win32 - * Add private flag to TorrentCreator plugin - * Use SVG for internal logo usage (except on Win32) - * Use theme for tray icon instead of hard-coded - * Properly release port on shutdown - * TorrentFiles plugin now has progress bars - * Removing torrent files no longer deletes files that weren't part of the torrent - * New max half-open connections setting to deal with cheap/broken routers - * Inherit UPnP fixes from libtorrent - * Use threading for everything, instead of spawning - -Deluge 0.5.5 (09 September 2007) - * Editing a torrent's tracker list is now persistent between sessions - * Persistence between sessions for Speed Limiter, Web Seed and Desired Ratio - plugins - * New wizard to aid first-time users with configuration - * Reorderable tabs and remember order (with exception of details tab) - * Fix losing data and having to re-download parts - * Fix password lock showing when main window is not hidden - * Get rid of the plugin manager and integrate it into preferences - * New Move torrent plugin - takes over for "move completed downloads" feature - and provides a "Move Torrent" option when right-clicking on a torrent - * Save column widths - * Queue order after restart fixes. - * Use payload instead of including protocol overhead to ease user confusion - of seeding torrents "downloading" - * New Web Seed plugin for adding URLs to torrents for http seeding - * Add FAST-extension (http://www.bittorrent.org/fast_extensions.html) - -Deluge 0.5.4.1 (10 August 2007) - * Add "Open containing folder" and "Open File" to the torrent and file - menu, respectively - * Load Blocklist plugin last and have it not lock up the interface during - import - * Add full allocation to preferences for clarification - * Catch SIGINT, SIGHUP, SIGTERM and Gnome logoff to quit properly - * Add send local info to developers - * Fix up pieces, peers and files plugins - * UPnP fixes - * Add ExtraStats plugin - * FreeBSD full allocation fix - * Added per torrent max upload slots and max connections preferences - * A lot of other less visible improvements - -Deluge 0.5.4 (06 August 2007) - - * Tray message includes session totals - * Ticket #198 - Display peers countries in the Peers tab. - * Ticket #474 - Multiple password prompts displayed - * Pause all/resume all in tray menu - * Peers and Files tabs are now plugins - * New Location plugin - * Option to use a random port every time - * Proxy system redone - you can now specify different information for each - type of proxy (DHT, peer, tracker, web-seed) - * TorrentPieces plugin to view piece updates and show pieces table per file - * EventLogger plugin to view/log every activity - * SpeedLimiter plugin, which allows you to set speed limits on a per-torrent - basis - * New release alerts - Client will inform user if their version of deluge is - outdated - -Deluge 0.5.3 (25 July 2007) - - * Added ChangeLog - * Ticket #53 - Added files priorities within torrent - * Ticket #111 - Remember directory of last added torrent - * Ticket #232 - Added Move completed downloads to feature - * Ticket #245 - Added ability to select torrent files before starting - * Ticked #368 - Added ability to prioritize first and last pieces of files - in torrents - * Ticket #371 - Proper full storage allocation of files on reiser4 and - ntfs-3g filesystems - * Ticket #420 - Show size of torrent minus size of unselected files as Total - Size - * Ticket #405 - Properly start in tray when run deluge --tray - * Ticket #437 - Gracefully upgrade from old versions - * Picking a file to not download now checks for compact_mode status to prevent - all sorts of problems such as downloading pieces into the wrong file - * RSS plugin inclusion - * Added ability to queue new torrents above completed ones when - seeds are set to queue at the bottom - * Added availability and piece size display in details, availability - column - * Added ability to automatically remove torrents when max share ratio is set - * Show text from clipboard in Add URL dialog only if it looks like an URL - * Added Torrent Notification plugin - * Added event handling callbacks for plugins - * Added ability to designate a torrent as private (in file selection dialog) - * Added merging trackers of duplicate torrents - * Details, Peers and Files tabs more responsible and their performance - greatly improved especially on torrents with many files and peers - * A lot of other less visible improvements - -Deluge 0.5.2 (05 July 2007) - * ticket #6 - Torrent creation built into main client - * ticket #315 - Plugins implemented as modules - * ticket #310 - Configuration options for PEX and UPnP - * ticket #390 - Individual file progress shown in File tab - * The usual slew of improvements - -Deluge 0.5.1 (11 June 2007) - * Peer Exchange - * ticket #254 - Encryption - * ticket #142 - UPnP + NATPMP - * Improved user interface - * Redesigned preferences dialog - * Proper startup and shutdown diff --git a/HACKING b/HACKING deleted file mode 100644 index 342c5bee8..000000000 --- a/HACKING +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2006 Marcos Pinto ('markybob') - -This is pretty much taken straight out of PEP 8, the "Style Guide for Python -Code" (http://www.python.org/dev/peps/pep-0008/) -More or less, if you try to submit a patch that doesn't follow this guide, odds -are your patch will be denied...unless it does some incredibly magnificient -things, in which case I *might* edit it. Don't bet on it, though. - -Here are the highlights: - Indents are FOUR (4) spaces. Not 8, not 5 or 2 and definitely NOT tab. - Limit all lines to a maximum of 80 characters. - Use UTF-8 encoding - Every single import should be on its own line - Avoid extraneous whitespace in the following situations: - Yes: spam(ham[1], {eggs: 2}) - No: spam( ham[ 1 ], { eggs: 2 } ) - Yes: spam(1) - No: spam (1) - Yes: if x == 4: print x, y; x, y = y, x - No: if x == 4 : print x , y ; x , y = y , x - Yes: dict['key'] = list[index] - No: dict ['key'] = list [index] - Yes: - x = 1 - y = 2 - long_variable = 3 - No: - x = 1 - y = 2 - long_variable = 3 - -Some more recommendations: - * "Don't repeat yourself (DRY). Every distinct concept and/or piece of - data should live in one, and only one, place. Redundancy is bad. - Normalization is good." (taken straight from django's Design philosophies) - * Try to use iterators/generators where applicable. The simplest change from - range to xrange is also good. - * In UI and deluge code for consistency we use notion of speed not rate. - Libtorrent mixes this usage and so do we on deluge-libtorrent boundary, - but all deluge only code should use speed. diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index caf2f3f03..000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,12 +0,0 @@ -include LICENSE -include README -include README.Packagers -include Makefile -include deluge.desktop -include deluge.png -include msgfmt.py -recursive-include libtorrent/ * -recursive-include glade/ *.glade -recursive-include pixmaps/ *.png *.svg -recursive-include plugins/ * -recursive-include po/ * diff --git a/Makefile b/Makefile deleted file mode 100644 index 28d3b707d..000000000 --- a/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# -# Makefile for Deluge -# -PYVER=`python -c "import sys; print sys.version[:3]"` -PREFIX ?= /usr -DESTDIR ?= ./ - -all: - python setup.py build - -tarball: - python setup.py sdist - mv dist/deluge-*.tar.gz $(DESTDIR) - -install: - python setup.py install --prefix=$(PREFIX) && /usr/bin/update-desktop-database; - -clean: - python setup.py clean - rm -rf ./build - rm msgfmt.pyc - find . -name *.pyc -exec rm {} \; - -uninstall: - -rm $(PREFIX)/bin/deluge - -rm -r $(PREFIX)/lib/python${PYVER}/site-packages/deluge - -rm -r $(PREFIX)/lib/python${PYVER}/site-packages/deluge-*.egg-info - -rm -r $(PREFIX)/share/deluge - -find ${PREFIX}/share/locale -name deluge.mo -exec rm {} \; - -rm $(PREFIX)/share/applications/deluge.desktop - -rm $(PREFIX)/share/pixmaps/deluge.png diff --git a/PKG-INFO b/PKG-INFO deleted file mode 100644 index ca3a2591d..000000000 --- a/PKG-INFO +++ /dev/null @@ -1,10 +0,0 @@ -Metadata-Version: 1.0 -Name: deluge -Version: 0.5.2 -Summary: A bittorrent client written in PyGTK -Home-page: http://deluge-torrent.org -Author: Zach Tibbitts, Alon Zakai, Marcos Pinto, Alex Dedul, Andrew Resch -Author-email: zach@collegegeek.org, kripkensteiner@gmail.com, marcospinto@dipconsultants.com, rotmer@gmail.com, alonzakai@gmail.com -License: GPLv2 -Description: UNKNOWN -Platform: UNKNOWN diff --git a/README b/README deleted file mode 100644 index 05c8bdd16..000000000 --- a/README +++ /dev/null @@ -1,103 +0,0 @@ -========================== - Deluge BitTorrent Client -========================== - -Authors: - Zach Tibbitts, aka zachtib - Alon Zakai, aka kripkenstein - Marcos Pinto, aka markybob - Andrew Resch, aka andar - Alex Dedul, aka plisk - -Homepage: http://deluge-torrent.org - -========================== -Contact/Support: -========================== - -We have two options available for support: - - Our Forum, at http://forum.deluge-torrent.org - or - Our IRC Channel, at #deluge on Freenode - -========================== -Installation Instructions: -========================== - -First, make sure you have the proper build dependencies installed. On a normal -Debian or Ubuntu system, those dependencies are: - -g++ -make -python-all-dev -python-all version >= 2.4 -python-dbus -python-gnome2-extras -python-gtk2 version >= 2.9 -python-notify -python-pyopenssl -librsvg2-common -python-xdg -python-support -libboost-dev >= 1.33.1 -libboost-thread-dev -libboost-date-time-dev -libboost-filesystem-dev -libboost-serialization-dev -libssl-dev -zlib1g-dev - -But the names of the packages may vary depending on your OS / distro. - -Once you have the needed libraries installed, build Deluge by running: - - $ make - -You shouldn't get any errors. Then run, as root (or by using sudo): - - $ make install - -and Deluge will be installed. By default, Deluge will be installed to the -prefix /usr. If you wish, you can install Deluge to a different prefix by -specifying it when you install it: - - $ PREFIX=yourprefixhere make install - -So, to install to /usr/local, run: - - $ PREFIX=/usr/local make install - -You can then run Deluge by executing: - - $ deluge - -========================== -Uninstallation/Upgrading: -========================== - -If you wish to upgrade from the older Deluge version please remove it first, -then install the latest version as per "Installation Instructions". If you -installed via the tarball, cd into the unpacked source tarball and then run, -as root (or by using sudo): - - $ make uninstall - -If you installed via the deb package, run as root (or by using sudo:) - $ dpkg --purge remove deluge-torrent - -Now install the latest version (and check out the additional notes). - -========================== -Additional Notes: -========================== - -1) On some distributions, boost libraries are renamed to have "-mt" at the end -(boost_thread_mt instead of boost_thread, for example), the "mt" indicating -"multithreaded". In some cases it appears the distros lack symlinks to connect -things. The solution is to either add symlinks from the short names to those -with "-mt", or to alter setup.py to look for the "-mt" versions. - -2) After upgrading your Deluge installation, it may fail to start. If this -happens to you, you need to remove your ~/.config/deluge directory to allow -Deluge to rebuild it's configuration file. diff --git a/README.Packagers b/README.Packagers deleted file mode 100644 index fe0b601de..000000000 --- a/README.Packagers +++ /dev/null @@ -1,8 +0,0 @@ -NOTE: Deluge 0.5.1 and newer uses an svn build of libtorrent. This build -differs from a clean libtorrent source checkout and has been hacked in order -to get it to work properly with Deluge. As a result, Deluge will likely not -build properly against a vanilla libtorrent 0.12 installation or a nightly -build oflibtorrent 0.13. It is recommended that you build against our included -libtorrent, as our build will not conflict with any installed libtorrent. - - - zachtib diff --git a/TODO b/TODO index 8b1378917..ae5631c2b 100644 --- a/TODO +++ b/TODO @@ -1 +1,23 @@ +For 0.6 release: +* Translations +* Add progress bars for downloading and importing lists instead of hanging (blocklist) +After 0.6 release: +* Address issue where torrents will redownload if the storage is moved outside + of deluge. +* Implement add by hash +* Figure out easy way for user-made plugins to add i18n support. +* Restart daemon function +* Docstrings! +* Add wizard +* Advanced (pieces) progress bar +* Add method for plugins to add labels +* Add context menus for labels.. ie. setting options for all torrents in label +* Implement caching in core +* Use the batch torrent status info as a cache for other torrent status requests +* Add number of torrents to labels +* Proxy stuff +* Webseed +* Enable/disable webui from within gtkui +* Notifications +* create a clamav plugin to scan files diff --git a/createicons.sh b/createicons.sh index cc3cd1d9c..114a822c5 100755 --- a/createicons.sh +++ b/createicons.sh @@ -1,5 +1,6 @@ #!/bin/bash -for size in 16 22 24 32 36 48 64 72 96 128 192 256; do mkdir -p icons/hicolor/\ -${size}x${size}/apps; rsvg-convert -w ${size} -h ${size} \ --o icons/hicolor/${size}x${size}/apps/deluge.png pixmaps/deluge.svg; mkdir -p \ -icons/scalable/apps/; cp pixmaps/deluge.svg icons/scalable/apps/deluge.svg; done +for size in 16 22 24 32 36 48 64 72 96 128 192 256; do mkdir -p deluge/data/\ +icons/hicolor/${size}x${size}/apps; rsvg-convert -w ${size} -h ${size} \ +-o deluge/data/icons/hicolor/${size}x${size}/apps/deluge.png deluge/data/pixmaps\ +/deluge.svg; mkdir -p deluge/data/icons/scalable/apps/; cp deluge/data/pixmaps/\ +deluge.svg deluge/data/icons/scalable/apps/deluge.svg; done diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 000000000..5f13cc0c8 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +deluge-torrent (0.6.0-svn3235-1) lenny; urgency=low + + * Daily Build + + -- Andrew Resch (andar) Tue, 17 Jun 2008 16:31:14 -0800 diff --git a/debian/changelog.debian-lenny b/debian/changelog.debian-lenny new file mode 100644 index 000000000..5f13cc0c8 --- /dev/null +++ b/debian/changelog.debian-lenny @@ -0,0 +1,5 @@ +deluge-torrent (0.6.0-svn3235-1) lenny; urgency=low + + * Daily Build + + -- Andrew Resch (andar) Tue, 17 Jun 2008 16:31:14 -0800 diff --git a/debian/changelog.debian-sid b/debian/changelog.debian-sid new file mode 100644 index 000000000..d6cd4de91 --- /dev/null +++ b/debian/changelog.debian-sid @@ -0,0 +1,5 @@ +deluge-torrent (0.6.0-svn3235-1) unstable; urgency=low + + * Daily Build + + -- Andrew Resch (andar) Tue, 17 Jun 2008 16:31:14 -0800 diff --git a/debian/changelog.ubuntu-gutsy b/debian/changelog.ubuntu-gutsy new file mode 100644 index 000000000..2417763b4 --- /dev/null +++ b/debian/changelog.ubuntu-gutsy @@ -0,0 +1,5 @@ +deluge-torrent (0.6.0-svn3235-1) gutsy; urgency=low + + * Daily Build + + -- Andrew Resch (andar) Tue, 17 Jun 2008 16:31:14 -0800 diff --git a/debian/changelog.ubuntu-hardy b/debian/changelog.ubuntu-hardy new file mode 100644 index 000000000..1ecb8d6a2 --- /dev/null +++ b/debian/changelog.ubuntu-hardy @@ -0,0 +1,5 @@ +deluge-torrent (0.6.0-svn3235-1) hardy; urgency=low + + * Daily Build + + -- Andrew Resch (andar) Tue, 17 Jun 2008 16:31:14 -0800 diff --git a/debian/compat b/debian/compat new file mode 100644 index 000000000..7ed6ff82d --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..94a7819d5 --- /dev/null +++ b/debian/control @@ -0,0 +1,21 @@ +Source: deluge-torrent +Section: net +Priority: optional +Maintainer: Andrew Resch (andar) +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, python-dbus, librsvg2-common, python-pyopenssl, python-setuptools +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/ diff --git a/debian/control.debian-lenny b/debian/control.debian-lenny new file mode 100644 index 000000000..a9eaaf67c --- /dev/null +++ b/debian/control.debian-lenny @@ -0,0 +1,19 @@ +Source: deluge-torrent +Section: net +Priority: optional +Maintainer: Andrew Resch (andar) +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, 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/ diff --git a/debian/control.debian-sid b/debian/control.debian-sid new file mode 100644 index 000000000..a9eaaf67c --- /dev/null +++ b/debian/control.debian-sid @@ -0,0 +1,19 @@ +Source: deluge-torrent +Section: net +Priority: optional +Maintainer: Andrew Resch (andar) +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, 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/ diff --git a/debian/control.ubuntu-gutsy b/debian/control.ubuntu-gutsy new file mode 100644 index 000000000..cc679ffb7 --- /dev/null +++ b/debian/control.ubuntu-gutsy @@ -0,0 +1,19 @@ +Source: deluge-torrent +Section: universe/net +Priority: optional +Maintainer: Andrew Resch (andar) +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, 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/ diff --git a/debian/control.ubuntu-hardy b/debian/control.ubuntu-hardy new file mode 100644 index 000000000..cc679ffb7 --- /dev/null +++ b/debian/control.ubuntu-hardy @@ -0,0 +1,19 @@ +Source: deluge-torrent +Section: universe/net +Priority: optional +Maintainer: Andrew Resch (andar) +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, 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/ diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 000000000..9a76a5798 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,103 @@ +This package was debianized by Adam Cécile (Le_Vert) on +Wed, 15 Nov 2006 22:03:13 +0100. + +It was downloaded from http://www.deluge-torrent.org/ + +Upstream Author: Zach Tibbitts + Alon Zakai + Marcos Pinto + +Copyright: (C) 2006, Zach Tibbitts + (C) 2006, Alon Zakai + +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 2 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/* are (C) 2006, A. Zakai ('Kripken') +and distributed unders term of GNU General Public License. + + This code is baded on libtorrent which is (C) 2003 Arvid Norberg and + distributed under terms of the 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-2006 Christopher + M. Kohlhoff 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. + +"po/*" 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-2007, Adam Cécile (Le_Vert) + and is licensed under the GPL, see above. diff --git a/debian/manpages b/debian/manpages new file mode 100644 index 000000000..cf243e191 --- /dev/null +++ b/debian/manpages @@ -0,0 +1 @@ +debian/deluge.1 diff --git a/debian/menu b/debian/menu new file mode 100644 index 000000000..d7c2ea5d1 --- /dev/null +++ b/debian/menu @@ -0,0 +1,3 @@ +?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" diff --git a/plugins/WebUi/lib/__init__.py b/debian/patches/00list similarity index 100% rename from plugins/WebUi/lib/__init__.py rename to debian/patches/00list diff --git a/debian/pyversions b/debian/pyversions new file mode 100644 index 000000000..95e3ba819 --- /dev/null +++ b/debian/pyversions @@ -0,0 +1 @@ +2.5 diff --git a/debian/pyversions.debian-lenny b/debian/pyversions.debian-lenny new file mode 100644 index 000000000..95e3ba819 --- /dev/null +++ b/debian/pyversions.debian-lenny @@ -0,0 +1 @@ +2.5 diff --git a/debian/pyversions.debian-sid b/debian/pyversions.debian-sid new file mode 100644 index 000000000..95e3ba819 --- /dev/null +++ b/debian/pyversions.debian-sid @@ -0,0 +1 @@ +2.5 diff --git a/debian/pyversions.ubuntu-gutsy b/debian/pyversions.ubuntu-gutsy new file mode 100644 index 000000000..95e3ba819 --- /dev/null +++ b/debian/pyversions.ubuntu-gutsy @@ -0,0 +1 @@ +2.5 diff --git a/debian/pyversions.ubuntu-hardy b/debian/pyversions.ubuntu-hardy new file mode 100644 index 000000000..95e3ba819 --- /dev/null +++ b/debian/pyversions.ubuntu-hardy @@ -0,0 +1 @@ +2.5 diff --git a/debian/rules b/debian/rules new file mode 100755 index 000000000..4ec9733c7 --- /dev/null +++ b/debian/rules @@ -0,0 +1,75 @@ +#!/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 diff --git a/debian/rules.debian-lenny b/debian/rules.debian-lenny new file mode 100755 index 000000000..7c4baf16a --- /dev/null +++ b/debian/rules.debian-lenny @@ -0,0 +1,75 @@ +#!/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.4 +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 diff --git a/debian/rules.debian-sid b/debian/rules.debian-sid new file mode 100755 index 000000000..7c4baf16a --- /dev/null +++ b/debian/rules.debian-sid @@ -0,0 +1,75 @@ +#!/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.4 +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 diff --git a/debian/rules.ubuntu-gutsy b/debian/rules.ubuntu-gutsy new file mode 100755 index 000000000..4ec9733c7 --- /dev/null +++ b/debian/rules.ubuntu-gutsy @@ -0,0 +1,75 @@ +#!/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 diff --git a/debian/rules.ubuntu-hardy b/debian/rules.ubuntu-hardy new file mode 100755 index 000000000..4ec9733c7 --- /dev/null +++ b/debian/rules.ubuntu-hardy @@ -0,0 +1,75 @@ +#!/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 diff --git a/deluge.desktop b/deluge.desktop deleted file mode 100644 index c81764adc..000000000 --- a/deluge.desktop +++ /dev/null @@ -1,13 +0,0 @@ -[Desktop Entry] -Version=1.0 -Encoding=UTF-8 -Name=Deluge BitTorrent Client -GenericName=BitTorrent Client -Comment=A GTK BitTorrent client written in Python and C++ -Exec=deluge -Icon=deluge.png -Terminal=false -Type=Application -Categories=Network; -StartupNotify=true -MimeType=application/x-bittorrent; diff --git a/deluge.png b/deluge.png deleted file mode 100644 index 3ac98d23f..000000000 Binary files a/deluge.png and /dev/null differ diff --git a/deluge/SimpleXMLRPCServer.py b/deluge/SimpleXMLRPCServer.py new file mode 100644 index 000000000..7a9f26faa --- /dev/null +++ b/deluge/SimpleXMLRPCServer.py @@ -0,0 +1,595 @@ +"""Simple XML-RPC Server. + +This module can be used to create simple XML-RPC servers +by creating a server and either installing functions, a +class instance, or by extending the SimpleXMLRPCServer +class. + +It can also be used to handle XML-RPC requests in a CGI +environment using CGIXMLRPCRequestHandler. + +A list of possible usage patterns follows: + +1. Install functions: + +server = SimpleXMLRPCServer(("localhost", 8000)) +server.register_function(pow) +server.register_function(lambda x,y: x+y, 'add') +server.serve_forever() + +2. Install an instance: + +class MyFuncs: + def __init__(self): + # make all of the string functions available through + # string.func_name + import string + self.string = string + def _listMethods(self): + # implement this method so that system.listMethods + # knows to advertise the strings methods + return list_public_methods(self) + \ + ['string.' + method for method in list_public_methods(self.string)] + def pow(self, x, y): return pow(x, y) + def add(self, x, y) : return x + y + +server = SimpleXMLRPCServer(("localhost", 8000)) +server.register_introspection_functions() +server.register_instance(MyFuncs()) +server.serve_forever() + +3. Install an instance with custom dispatch method: + +class Math: + def _listMethods(self): + # this method must be present for system.listMethods + # to work + return ['add', 'pow'] + def _methodHelp(self, method): + # this method must be present for system.methodHelp + # to work + if method == 'add': + return "add(2,3) => 5" + elif method == 'pow': + return "pow(x, y[, z]) => number" + else: + # By convention, return empty + # string if no help is available + return "" + def _dispatch(self, method, params): + if method == 'pow': + return pow(*params) + elif method == 'add': + return params[0] + params[1] + else: + raise 'bad method' + +server = SimpleXMLRPCServer(("localhost", 8000)) +server.register_introspection_functions() +server.register_instance(Math()) +server.serve_forever() + +4. Subclass SimpleXMLRPCServer: + +class MathServer(SimpleXMLRPCServer): + def _dispatch(self, method, params): + try: + # We are forcing the 'export_' prefix on methods that are + # callable through XML-RPC to prevent potential security + # problems + func = getattr(self, 'export_' + method) + except AttributeError: + raise Exception('method "%s" is not supported' % method) + else: + return func(*params) + + def export_add(self, x, y): + return x + y + +server = MathServer(("localhost", 8000)) +server.serve_forever() + +5. CGI script: + +server = CGIXMLRPCRequestHandler() +server.register_function(pow) +server.handle_request() +""" + +# Written by Brian Quinlan (brian@sweetapp.com). +# Based on code written by Fredrik Lundh. + +import xmlrpclib +from xmlrpclib import Fault +import SocketServer +import BaseHTTPServer +import sys +import os +try: + import fcntl +except ImportError: + fcntl = None + +def resolve_dotted_attribute(obj, attr, allow_dotted_names=True): + """resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d + + Resolves a dotted attribute name to an object. Raises + an AttributeError if any attribute in the chain starts with a '_'. + + If the optional allow_dotted_names argument is false, dots are not + supported and this function operates similar to getattr(obj, attr). + """ + + if allow_dotted_names: + attrs = attr.split('.') + else: + attrs = [attr] + + for i in attrs: + if i.startswith('_'): + raise AttributeError( + 'attempt to access private attribute "%s"' % i + ) + else: + obj = getattr(obj,i) + return obj + +def list_public_methods(obj): + """Returns a list of attribute strings, found in the specified + object, which represent callable attributes""" + + return [member for member in dir(obj) + if not member.startswith('_') and + callable(getattr(obj, member))] + +def remove_duplicates(lst): + """remove_duplicates([2,2,2,1,3,3]) => [3,1,2] + + Returns a copy of a list without duplicates. Every list + item must be hashable and the order of the items in the + resulting list is not defined. + """ + u = {} + for x in lst: + u[x] = 1 + + return u.keys() + +class SimpleXMLRPCDispatcher: + """Mix-in class that dispatches XML-RPC requests. + + This class is used to register XML-RPC method handlers + and then to dispatch them. There should never be any + reason to instantiate this class directly. + """ + + def __init__(self, allow_none, encoding): + self.funcs = {} + self.instance = None + self.allow_none = allow_none + self.encoding = encoding + + def register_instance(self, instance, allow_dotted_names=False): + """Registers an instance to respond to XML-RPC requests. + + Only one instance can be installed at a time. + + If the registered instance has a _dispatch method then that + method will be called with the name of the XML-RPC method and + its parameters as a tuple + e.g. instance._dispatch('add',(2,3)) + + If the registered instance does not have a _dispatch method + then the instance will be searched to find a matching method + and, if found, will be called. Methods beginning with an '_' + are considered private and will not be called by + SimpleXMLRPCServer. + + If a registered function matches a XML-RPC request, then it + will be called instead of the registered instance. + + If the optional allow_dotted_names argument is true and the + instance does not have a _dispatch method, method names + containing dots are supported and resolved, as long as none of + the name segments start with an '_'. + + *** SECURITY WARNING: *** + + Enabling the allow_dotted_names options allows intruders + to access your module's global variables and may allow + intruders to execute arbitrary code on your machine. Only + use this option on a secure, closed network. + + """ + + self.instance = instance + self.allow_dotted_names = allow_dotted_names + + def register_function(self, function, name = None): + """Registers a function to respond to XML-RPC requests. + + The optional name argument can be used to set a Unicode name + for the function. + """ + + if name is None: + name = function.__name__ + self.funcs[name] = function + + def register_introspection_functions(self): + """Registers the XML-RPC introspection methods in the system + namespace. + + see http://xmlrpc.usefulinc.com/doc/reserved.html + """ + + self.funcs.update({'system.listMethods' : self.system_listMethods, + 'system.methodSignature' : self.system_methodSignature, + 'system.methodHelp' : self.system_methodHelp}) + + def register_multicall_functions(self): + """Registers the XML-RPC multicall method in the system + namespace. + + see http://www.xmlrpc.com/discuss/msgReader$1208""" + + self.funcs.update({'system.multicall' : self.system_multicall}) + + def _marshaled_dispatch(self, data, dispatch_method = None): + """Dispatches an XML-RPC method from marshalled (XML) data. + + XML-RPC methods are dispatched from the marshalled (XML) data + using the _dispatch method and the result is returned as + marshalled data. For backwards compatibility, a dispatch + function can be provided as an argument (see comment in + SimpleXMLRPCRequestHandler.do_POST) but overriding the + existing method through subclassing is the prefered means + of changing method dispatch behavior. + """ + + try: + params, method = xmlrpclib.loads(data) + + # generate response + if dispatch_method is not None: + response = dispatch_method(method, params) + else: + response = self._dispatch(method, params) + # wrap response in a singleton tuple + response = (response,) + response = xmlrpclib.dumps(response, methodresponse=1, + allow_none=self.allow_none, encoding=self.encoding) + except Fault, fault: + response = xmlrpclib.dumps(fault, allow_none=self.allow_none, + encoding=self.encoding) + except: + # report exception back to server + response = xmlrpclib.dumps( + xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)), + encoding=self.encoding, allow_none=self.allow_none, + ) + + return response + + def system_listMethods(self): + """system.listMethods() => ['add', 'subtract', 'multiple'] + + Returns a list of the methods supported by the server.""" + + methods = self.funcs.keys() + if self.instance is not None: + # Instance can implement _listMethod to return a list of + # methods + if hasattr(self.instance, '_listMethods'): + methods = remove_duplicates( + methods + self.instance._listMethods() + ) + # if the instance has a _dispatch method then we + # don't have enough information to provide a list + # of methods + elif not hasattr(self.instance, '_dispatch'): + methods = remove_duplicates( + methods + list_public_methods(self.instance) + ) + methods.sort() + return methods + + def system_methodSignature(self, method_name): + """system.methodSignature('add') => [double, int, int] + + Returns a list describing the signature of the method. In the + above example, the add method takes two integers as arguments + and returns a double result. + + This server does NOT support system.methodSignature.""" + + # See http://xmlrpc.usefulinc.com/doc/sysmethodsig.html + + return 'signatures not supported' + + def system_methodHelp(self, method_name): + """system.methodHelp('add') => "Adds two integers together" + + Returns a string containing documentation for the specified method.""" + + method = None + if self.funcs.has_key(method_name): + method = self.funcs[method_name] + elif self.instance is not None: + # Instance can implement _methodHelp to return help for a method + if hasattr(self.instance, '_methodHelp'): + return self.instance._methodHelp(method_name) + # if the instance has a _dispatch method then we + # don't have enough information to provide help + elif not hasattr(self.instance, '_dispatch'): + try: + method = resolve_dotted_attribute( + self.instance, + method_name, + self.allow_dotted_names + ) + except AttributeError: + pass + + # Note that we aren't checking that the method actually + # be a callable object of some kind + if method is None: + return "" + else: + import pydoc + return pydoc.getdoc(method) + + def system_multicall(self, call_list): + """system.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => \ +[[4], ...] + + Allows the caller to package multiple XML-RPC calls into a single + request. + + See http://www.xmlrpc.com/discuss/msgReader$1208 + """ + + results = [] + for call in call_list: + method_name = call['methodName'] + params = call['params'] + + try: + # XXX A marshalling error in any response will fail the entire + # multicall. If someone cares they should fix this. + results.append([self._dispatch(method_name, params)]) + except Fault, fault: + results.append( + {'faultCode' : fault.faultCode, + 'faultString' : fault.faultString} + ) + except: + results.append( + {'faultCode' : 1, + 'faultString' : "%s:%s" % (sys.exc_type, sys.exc_value)} + ) + return results + + def _dispatch(self, method, params): + """Dispatches the XML-RPC method. + + XML-RPC calls are forwarded to a registered function that + matches the called XML-RPC method name. If no such function + exists then the call is forwarded to the registered instance, + if available. + + If the registered instance has a _dispatch method then that + method will be called with the name of the XML-RPC method and + its parameters as a tuple + e.g. instance._dispatch('add',(2,3)) + + If the registered instance does not have a _dispatch method + then the instance will be searched to find a matching method + and, if found, will be called. + + Methods beginning with an '_' are considered private and will + not be called. + """ + + func = None + try: + # check to see if a matching function has been registered + func = self.funcs[method] + except KeyError: + if self.instance is not None: + # check for a _dispatch method + if hasattr(self.instance, '_dispatch'): + return self.instance._dispatch(method, params) + else: + # call instance method directly + try: + func = resolve_dotted_attribute( + self.instance, + method, + self.allow_dotted_names + ) + except AttributeError: + pass + + if func is not None: + return func(*params) + else: + raise Exception('method "%s" is not supported' % method) + +class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): + """Simple XML-RPC request handler class. + + Handles all HTTP POST requests and attempts to decode them as + XML-RPC requests. + """ + + # Class attribute listing the accessible path components; + # paths not on this list will result in a 404 error. + rpc_paths = ('/', '/RPC2') + + def is_rpc_path_valid(self): + if self.rpc_paths: + return self.path in self.rpc_paths + else: + # If .rpc_paths is empty, just assume all paths are legal + return True + + def do_POST(self): + """Handles the HTTP POST request. + + Attempts to interpret all HTTP POST requests as XML-RPC calls, + which are forwarded to the server's _dispatch method for handling. + """ + + # Check that the path is legal + if not self.is_rpc_path_valid(): + self.report_404() + return + + try: + # Get arguments by reading body of request. + # We read this in chunks to avoid straining + # socket.read(); around the 10 or 15Mb mark, some platforms + # begin to have problems (bug #792570). + max_chunk_size = 10*1024*1024 + size_remaining = int(self.headers["content-length"]) + L = [] + while size_remaining: + chunk_size = min(size_remaining, max_chunk_size) + L.append(self.rfile.read(chunk_size)) + size_remaining -= len(L[-1]) + data = ''.join(L) + + # In previous versions of SimpleXMLRPCServer, _dispatch + # could be overridden in this class, instead of in + # SimpleXMLRPCDispatcher. To maintain backwards compatibility, + # check to see if a subclass implements _dispatch and dispatch + # using that method if present. + response = self.server._marshaled_dispatch( + data, getattr(self, '_dispatch', None) + ) + except: # This should only happen if the module is buggy + # internal error, report as HTTP server error + self.send_response(500) + self.end_headers() + else: + # got a valid XML RPC response + self.send_response(200) + self.send_header("Content-type", "text/xml") + self.send_header("Content-length", str(len(response))) + self.end_headers() + self.wfile.write(response) + + # shut down the connection + self.wfile.flush() + self.connection.shutdown(1) + + def report_404 (self): + # Report a 404 error + self.send_response(404) + response = 'No such page' + self.send_header("Content-type", "text/plain") + self.send_header("Content-length", str(len(response))) + self.end_headers() + self.wfile.write(response) + # shut down the connection + self.wfile.flush() + self.connection.shutdown(1) + + def log_request(self, code='-', size='-'): + """Selectively log an accepted request.""" + + if self.server.logRequests: + BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size) + +class SimpleXMLRPCServer(SocketServer.TCPServer, + SimpleXMLRPCDispatcher): + """Simple XML-RPC server. + + Simple XML-RPC server that allows functions and a single instance + to be installed to handle requests. The default implementation + attempts to dispatch XML-RPC calls to the functions or instance + installed in the server. Override the _dispatch method inhereted + from SimpleXMLRPCDispatcher to change this behavior. + """ + + allow_reuse_address = True + + def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler, + logRequests=True, allow_none=False, encoding=None): + self.logRequests = logRequests + + SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding) + SocketServer.TCPServer.__init__(self, addr, requestHandler) + + # [Bug #1222790] If possible, set close-on-exec flag; if a + # method spawns a subprocess, the subprocess shouldn't have + # the listening socket open. + if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'): + flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD) + flags |= fcntl.FD_CLOEXEC + fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags) + +class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): + """Simple handler for XML-RPC data passed through CGI.""" + + def __init__(self, allow_none=False, encoding=None): + SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding) + + def handle_xmlrpc(self, request_text): + """Handle a single XML-RPC request""" + + response = self._marshaled_dispatch(request_text) + + print 'Content-Type: text/xml' + print 'Content-Length: %d' % len(response) + print + sys.stdout.write(response) + + def handle_get(self): + """Handle a single HTTP GET request. + + Default implementation indicates an error because + XML-RPC uses the POST method. + """ + + code = 400 + message, explain = \ + BaseHTTPServer.BaseHTTPRequestHandler.responses[code] + + response = BaseHTTPServer.DEFAULT_ERROR_MESSAGE % \ + { + 'code' : code, + 'message' : message, + 'explain' : explain + } + print 'Status: %d %s' % (code, message) + print 'Content-Type: text/html' + print 'Content-Length: %d' % len(response) + print + sys.stdout.write(response) + + def handle_request(self, request_text = None): + """Handle a single XML-RPC request passed through a CGI post method. + + If no XML data is given then it is read from stdin. The resulting + XML-RPC response is printed to stdout along with the correct HTTP + headers. + """ + + if request_text is None and \ + os.environ.get('REQUEST_METHOD', None) == 'GET': + self.handle_get() + else: + # POST data is normally available through stdin + if request_text is None: + request_text = sys.stdin.read() + + self.handle_xmlrpc(request_text) + +if __name__ == '__main__': + print 'Running XML-RPC server on port 8000' + server = SimpleXMLRPCServer(("localhost", 8000)) + server.register_function(pow) + server.register_function(lambda x,y: x+y, 'add') + server.serve_forever() diff --git a/deluge/__init__.py b/deluge/__init__.py new file mode 100644 index 000000000..1836ded86 --- /dev/null +++ b/deluge/__init__.py @@ -0,0 +1 @@ +"""Deluge""" diff --git a/deluge/common.py b/deluge/common.py new file mode 100644 index 000000000..1ff4a53e1 --- /dev/null +++ b/deluge/common.py @@ -0,0 +1,354 @@ +# +# common.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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. + +"""Common functions for various parts of Deluge to use.""" + +import os + +import pkg_resources +import xdg, xdg.BaseDirectory + +LT_TORRENT_STATE = { + "Queued": 0, + "Checking": 1, + "Connecting": 2, + "Downloading Metadata": 3, + "Downloading": 4, + "Finished": 5, + "Seeding": 6, + "Allocating": 7, + "Paused": 8, + 0: "Queued", + 1: "Checking", + 2: "Connecting", + 3: "Downloading Metadata", + 4: "Downloading", + 5: "Finished", + 6: "Seeding", + 7: "Allocating", + 8: "Paused" +} + +TORRENT_STATE = [ + "Allocating", + "Checking", + "Downloading", + "Seeding", + "Paused", + "Error", + "Queued" +] + +FILE_PRIORITY = { + 0: "Do Not Download", + 1: "Normal Priority", + 2: "High Priority", + 5: "Highest Priority", + "Do Not Download": 0, + "Normal Priority": 1, + "High Priority": 2, + "Highest Priority": 5 +} + +def get_version(): + """Returns the program version from the egg metadata""" + return pkg_resources.require("Deluge")[0].version.split("r")[0] + +def get_revision(): + revision = "" + try: + f = open(pkg_resources.resource_filename("deluge", os.path.join("data", "revision"))) + revision = f.read() + f.close() + except IOError, e: + pass + + return revision + +def get_default_config_dir(filename=None): + """ Returns the config path if no filename is specified + Returns the config directory + filename as a path if filename is specified + """ + if windows_check(): + if filename: + return os.path.join(os.environ.get("APPDATA"), "deluge", filename) + else: + return os.path.join(os.environ.get("APPDATA"), "deluge") + else: + if filename: + return os.path.join(xdg.BaseDirectory.save_config_path("deluge"), filename) + else: + return xdg.BaseDirectory.save_config_path("deluge") + +def get_default_download_dir(): + """Returns the default download directory""" + if windows_check(): + return os.path.expanduser("~") + else: + return os.environ.get("HOME") + +def windows_check(): + """Checks if the current platform is Windows. Returns True if it is Windows + and False if not.""" + import platform + if platform.system() in ('Windows', 'Microsoft'): + return True + else: + return False + +def get_pixmap(fname): + """Returns a pixmap file included with deluge""" + return pkg_resources.resource_filename("deluge", os.path.join("data", \ + "pixmaps", fname)) + +def get_logo(size): + """Returns a deluge logo pixbuf based on the size parameter.""" + import gtk + if windows_check(): + return gtk.gdk.pixbuf_new_from_file_at_size(get_pixmap("deluge.png"), \ + size, size) + else: + return gtk.gdk.pixbuf_new_from_file_at_size(get_pixmap("deluge.svg"), \ + size, size) + +def open_file(path): + """Opens a file or folder.""" + if windows_check(): + os.startfile("'%s'" % path) + else: + os.popen("xdg-open '%s'" % path) + +def open_url_in_browser(url): + """Opens link in the desktop's default browser""" + def start_browser(): + import threading + import webbrowser + class BrowserThread(threading.Thread): + def __init__(self, url): + threading.Thread.__init__(self) + self.url = url + def run(self): + webbrowser.open(self.url) + BrowserThread(url).start() + return False + + import gobject + gobject.idle_add(start_browser) + + +def build_menu_radio_list(value_list, callback, pref_value=None, + suffix=None, show_notset=False, notset_label=None, notset_lessthan=0, + show_other=False, show_activated=False, activated_label=None): + # Build a menu with radio menu items from a list and connect them to + # the callback. The pref_value is what you would like to test for the + # default active radio item. + import gtk + if notset_label is None: + notset_label = _("Unlimited") + + if activated_label is None: + activated_label = _("Activated") + + menu = gtk.Menu() + group = None + if show_activated is False: + if pref_value > -1 and pref_value not in value_list: + value_list.pop() + value_list.append(pref_value) + + for value in sorted(value_list): + if suffix != None: + menuitem = gtk.RadioMenuItem(group, str(value) + " " + \ + suffix) + else: + menuitem = gtk.RadioMenuItem(group, str(value)) + + group = menuitem + + if value == pref_value and pref_value != None: + menuitem.set_active(True) + + if callback != None: + menuitem.connect("toggled", callback) + + menu.append(menuitem) + + if show_activated is True: + for value in sorted(value_list): + menuitem = gtk.RadioMenuItem(group, str(activated_label)) + + group = menuitem + + if value == pref_value and pref_value != None: + menuitem.set_active(True) + + if callback != None: + menuitem.connect("toggled", callback) + + menu.append(menuitem) + + if show_notset: + menuitem = gtk.RadioMenuItem(group, notset_label) + if pref_value < notset_lessthan and pref_value != None: + menuitem.set_active(True) + if show_activated and pref_value == 1: + menuitem.set_active(True) + menuitem.connect("toggled", callback) + menu.append(menuitem) + + # Add the Other... menuitem + if show_other is True: + menuitem = gtk.SeparatorMenuItem() + menu.append(menuitem) + menuitem = gtk.MenuItem(_("Other...")) + menuitem.connect("activate", callback) + menu.append(menuitem) + + return menu + +def show_other_dialog(string, default=None): + """Shows a dialog to get an 'other' speed and return the value""" + import gtk + import gtk.glade + dialog_glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/dgtkpopups.glade")) + speed_dialog = dialog_glade.get_widget("speed_dialog") + spin_title = dialog_glade.get_widget("spin_title") + spin_title.set_text(_("%s" % string)) + spin_speed = dialog_glade.get_widget("spin_speed") + if default != None: + spin_speed.set_value(default) + spin_speed.select_region(0, -1) + response = speed_dialog.run() + if response == 1: # OK Response + value = spin_speed.get_value() + else: + speed_dialog.destroy() + return None + + speed_dialog.destroy() + return value + +## Formatting text functions + +def fsize(fsize_b): + """Returns formatted string describing filesize + fsize_b should be in bytes + Returned value will be in either KB, MB, or GB + """ + fsize_kb = fsize_b / 1024.0 + if fsize_kb < 1000: + return "%.1f KiB" % fsize_kb + fsize_mb = fsize_kb / 1024.0 + if fsize_mb < 1000: + return "%.1f MiB" % fsize_mb + fsize_gb = fsize_mb / 1024.0 + return "%.1f GiB" % fsize_gb + +def fpcnt(dec): + """Returns a formatted string representing a percentage""" + return '%.2f%%' % (dec * 100) + +def fspeed(bps): + """Returns a formatted string representing transfer speed""" + return '%s/s' % (fsize(bps)) + +def fpeer(num_peers, total_peers): + """Returns a formatted string num_peers (total_peers)""" + if total_peers > -1: + return "%d (%d)" % (num_peers, total_peers) + else: + return "%d" % num_peers + +def ftime(seconds): + """Returns a formatted time string""" + if seconds == 0: + return "Infinity" + if seconds < 60: + return '%ds' % (seconds) + minutes = seconds / 60 + seconds = seconds % 60 + if minutes < 60: + return '%dm %ds' % (minutes, seconds) + hours = minutes / 60 + minutes = minutes % 60 + if hours < 24: + return '%dh %dm' % (hours, minutes) + days = hours / 24 + hours = hours % 24 + if days < 7: + return '%dd %dh' % (days, hours) + weeks = days / 7 + days = days % 7 + if weeks < 10: + return '%dw %dd' % (weeks, days) + return 'unknown' + +def is_url(url): + """A simple regex test to check if the URL is valid.""" + import re + return bool(re.search('^(https?|ftp)://', url)) + +def fetch_url(url): + """Downloads a torrent file from a given + URL and checks the file's validity.""" + import urllib + from deluge.log import LOG as log + try: + filename, headers = urllib.urlretrieve(url) + except IOError: + log.debug("Network error while trying to fetch torrent from %s", url) + else: + if filename.endswith(".torrent") or headers["content-type"] ==\ + "application/x-bittorrent": + return filename + else: + log.debug("URL doesn't appear to be a valid torrent file: %s", url) + return None + +def pythonize(var): + """Translates DBUS types back to basic Python types.""" + if isinstance(var, list): + return [pythonize(value) for value in var] + if isinstance(var, tuple): + return tuple([pythonize(value) for value in var]) + if isinstance(var, dict): + return dict( + [(pythonize(key), pythonize(value)) for key, value in var.iteritems()] + ) + + for klass in [unicode, str, bool, int, float, long]: + if isinstance(var, klass): + return klass(var) + return var diff --git a/deluge/component.py b/deluge/component.py new file mode 100644 index 000000000..1b2a07347 --- /dev/null +++ b/deluge/component.py @@ -0,0 +1,229 @@ +# +# component.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 gobject +from deluge.log import LOG as log + +COMPONENT_STATE = [ + "Stopped", + "Started", + "Paused" +] + +class Component: + def __init__(self, name, interval=1000, depend=None): + # Register with the ComponentRegistry + register(name, self, depend) + self._interval = interval + self._timer = None + self._state = COMPONENT_STATE.index("Stopped") + + def get_state(self): + return self._state + + def start(self): + pass + + def _start(self): + self._state = COMPONENT_STATE.index("Started") + if self._update(): + self._timer = gobject.timeout_add(self._interval, self._update) + + def stop(self): + pass + + def _stop(self): + self._state = COMPONENT_STATE.index("Stopped") + try: + gobject.source_remove(self._timer) + except: + pass + + def _pause(self): + self._state = COMPONENT_STATE.index("Paused") + try: + gobject.source_remove(self._timer) + except: + pass + + def _resume(self): + self._start() + + def shutdown(self): + pass + + def _update(self): + try: + self.update() + except AttributeError: + # This will stop the timer since the component doesn't have an + # update method. + return False + return True + + +class ComponentRegistry: + def __init__(self): + self.components = {} + self.depend = {} + + def register(self, name, obj, depend): + """Registers a component.. depend must be list or None""" + log.debug("Registered %s with ComponentRegistry..", name) + self.components[name] = obj + if depend != None: + self.depend[name] = depend + + def get(self, name): + """Returns a reference to the component 'name'""" + return self.components[name] + + def start(self): + """Starts all components""" + for component in self.components.keys(): + self.start_component(component) + + def start_component(self, name): + """Starts a component""" + # Check to see if this component has any dependencies + if self.depend.has_key(name): + for depend in self.depend[name]: + self.start_component(depend) + # Only start if the component is stopped. + if self.components[name].get_state() == \ + COMPONENT_STATE.index("Stopped"): + log.debug("Starting component %s..", name) + self.components[name].start() + self.components[name]._start() + + def stop(self): + """Stops all components""" + for component in self.components.keys(): + self.stop_component(component) + + def stop_component(self, component): + if self.components[component].get_state() != \ + COMPONENT_STATE.index("Stopped"): + log.debug("Stopping component %s..", component) + self.components[component].stop() + self.components[component]._stop() + + def pause(self): + """Pauses all components. Stops calling update()""" + for component in self.components.keys(): + self.pause_component(component) + + def pause_component(self, component): + if self.components[component].get_state() not in \ + [COMPONENT_STATE.index("Paused"), COMPONENT_STATE.index("Stopped")]: + log.debug("Pausing component %s..", component) + self.components[component]._pause() + + def resume(self): + """Resumes all components. Starts calling update()""" + for component in self.components.keys(): + self.resume_component(component) + + def resume_component(self, component): + if self.components[component].get_state() == COMPONENT_STATE.index("Paused"): + log.debug("Resuming component %s..", component) + self.components[component]._resume() + + def update(self): + """Updates all components""" + for component in self.components.keys(): + # Only update the component if it's started + if self.components[component].get_state() == \ + COMPONENT_STATE.index("Started"): + self.components[component].update() + + return True + + def shutdown(self): + """Shuts down all components. This should be called when the program + exits so that components can do any necessary clean-up.""" + # Stop all components first + self.stop() + for component in self.components.keys(): + log.debug("Shutting down component %s..", component) + try: + self.components[component].shutdown() + except Exception, e: + log.debug("Unable to call shutdown(): %s", e) + + +_ComponentRegistry = ComponentRegistry() + +def register(name, obj, depend=None): + """Registers a component with the registry""" + _ComponentRegistry.register(name, obj, depend) + +def start(component=None): + """Starts all components""" + if component == None: + _ComponentRegistry.start() + else: + _ComponentRegistry.start_component(component) + +def stop(component=None): + """Stops all or specified components""" + if component == None: + _ComponentRegistry.stop() + else: + _ComponentRegistry.stop_component(component) + +def pause(component=None): + """Pauses all or specificed components""" + if component == None: + _ComponentRegistry.pause() + else: + _ComponentRegistry.pause_component(component) + +def resume(component=None): + """Resumes all or specificed components""" + if component == None: + _ComponentRegistry.resume() + else: + _ComponentRegistry.resume_component(component) + +def update(): + """Updates all components""" + _ComponentRegistry.update() + +def shutdown(): + """Shutdowns all components""" + _ComponentRegistry.shutdown() + +def get(component): + """Return a reference to the component""" + return _ComponentRegistry.get(component) diff --git a/deluge/config.py b/deluge/config.py new file mode 100644 index 000000000..b0041fb60 --- /dev/null +++ b/deluge/config.py @@ -0,0 +1,176 @@ +# +# config.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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. + +"""Configuration class used to access/create/modify configuration files.""" + +import cPickle +import os.path + +import gobject +import deluge.common +from deluge.log import LOG as log + +class Config: + """This class is used to access configuration files.""" + + def __init__(self, filename, defaults=None, config_dir=None): + log.debug("Config created with filename: %s", filename) + log.debug("Config defaults: %s", defaults) + self.config = {} + self.previous_config = {} + self.set_functions = {} + self._change_callback = None + + # If defaults is not None then we need to use "defaults". + if defaults != None: + self.config = defaults + + # Load the config from file in the config_dir + if config_dir == None: + self.config_file = deluge.common.get_default_config_dir(filename) + else: + self.config_file = os.path.join(config_dir, filename) + + self.load(self.config_file) + # Save + self.save() + + def __del__(self): + self.save() + + def load(self, filename=None): + """Load a config file either by 'filename' or the filename set during + construction of this object.""" + # Use self.config_file if filename is None + if filename is None: + filename = self.config_file + try: + # Un-pickle the file and update the config dictionary + pkl_file = open(filename, "rb") + filedump = cPickle.load(pkl_file) + self.config.update(filedump) + pkl_file.close() + except IOError: + log.warning("IOError: Unable to load file '%s'", filename) + except EOFError: + pkl_file.close() + + def save(self, filename=None): + """Save configuration to either 'filename' or the filename set during + construction of this object.""" + # Saves the config dictionary + if filename is None: + filename = self.config_file + # Check to see if the current config differs from the one on disk + # We will only write a new config file if there is a difference + try: + pkl_file = open(filename, "rb") + filedump = cPickle.load(pkl_file) + pkl_file.close() + if filedump == self.config: + # The config has not changed so lets just return + return + except (EOFError, IOError): + log.warning("IOError: Unable to open file: '%s'", filename) + + try: + pkl_file = open(filename, "wb") + cPickle.dump(self.config, pkl_file) + pkl_file.close() + except IOError: + log.warning("IOError: Unable to save file '%s'", filename) + + def set(self, key, value): + """Set the 'key' with 'value'.""" + # Sets the "key" with "value" in the config dict + if self.config[key] != value: + log.debug("Setting '%s' to %s of %s", key, value, type(value)) + # Make a copy of the current config prior to changing it + self.previous_config = self.config.copy() + self.config[key] = value + # Run the set_function for this key if any + try: + gobject.idle_add(self.set_functions[key], key, value) + except KeyError: + pass + try: + gobject.idle_add(self._change_callback, key, value) + except: + pass + + def get(self, key): + """Get the value of 'key'. If it is an invalid key then get() will + return None.""" + # Attempts to get the "key" value and returns None if the key is + # invalid + try: + value = self.config[key] + log.debug("Getting '%s' as %s of %s", key, value, type(value)) + return value + except KeyError: + log.warning("Key does not exist, returning None") + return None + + def get_config(self): + """Returns the entire configuration as a dictionary.""" + return self.config + + def get_previous_config(self): + """Returns the config prior to the last set()""" + return self.previous_config + + def register_change_callback(self, callback): + """Registers a callback that will be called when a value is changed""" + self._change_callback = callback + + def register_set_function(self, key, function, apply_now=True): + """Register a function to be run when a config value changes.""" + log.debug("Registering function for %s key..", key) + self.set_functions[key] = function + # Run the function now if apply_now is set + if apply_now: + self.set_functions[key](key, self.config[key]) + return + + def apply_all(self): + """Runs all set functions""" + log.debug("Running all set functions..") + for key in self.set_functions.keys(): + self.set_functions[key](key, self.config[key]) + + def __getitem__(self, key): + return self.config[key] + + def __setitem__(self, key, value): + self.set(key, value) + diff --git a/deluge/configmanager.py b/deluge/configmanager.py new file mode 100644 index 000000000..2870484b9 --- /dev/null +++ b/deluge/configmanager.py @@ -0,0 +1,112 @@ +# +# configmanager.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 gobject +import os +import os.path + +import deluge.common +from deluge.log import LOG as log +from deluge.config import Config + +class _ConfigManager: + def __init__(self): + log.debug("ConfigManager started..") + self.config_files = {} + self.config_directory = deluge.common.get_default_config_dir() + # Set a 5 minute timer to call save() + gobject.timeout_add(300000, self.save) + + def __del__(self): + log.debug("ConfigManager stopping..") + del self.config_files + + def set_config_dir(self, directory): + """Sets the config directory""" + if directory == None: + return + log.info("Setting config directory to: %s", directory) + if not os.path.exists(directory): + # Try to create the config folder if it doesn't exist + try: + os.makedirs(directory) + except Exception, e: + log.warning("Unable to make config directory: %s", e) + + self.config_directory = directory + + def get_config_dir(self): + log.debug("get_config_dir: %s", self.config_directory) + return self.config_directory + + def close(self, config): + """Closes a config file.""" + try: + del self.config_files[config] + except KeyError: + pass + + def save(self): + """Saves all the configs to disk.""" + for key in self.config_files.keys(): + self.config_files[key].save() + # We need to return True to keep the timer active + return True + + def get_config(self, config_file, defaults=None): + """Get a reference to the Config object for this filename""" + log.debug("Getting config '%s'", config_file) + # Create the config object if not already created + if config_file not in self.config_files.keys(): + self.config_files[config_file] = Config(config_file, defaults, self.config_directory) + + return self.config_files[config_file] + +# Singleton functions +_configmanager = _ConfigManager() + +def ConfigManager(config, defaults=None): + return _configmanager.get_config(config, defaults) + +def set_config_dir(directory): + """Sets the config directory, else just uses default""" + return _configmanager.set_config_dir(directory) + +def get_config_dir(filename=None): + if filename != None: + return os.path.join(_configmanager.get_config_dir(), filename) + else: + return _configmanager.get_config_dir() + +def close(config): + return _configmanager.close(config) diff --git a/deluge/core/__init__.py b/deluge/core/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/deluge/core/alertmanager.py b/deluge/core/alertmanager.py new file mode 100644 index 000000000..b12dd96d1 --- /dev/null +++ b/deluge/core/alertmanager.py @@ -0,0 +1,109 @@ +# +# alertmanager.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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. + +"""The AlertManager handles all the libtorrent alerts.""" + +import gobject + +import deluge.component as component +import deluge.libtorrent as lt +from deluge.log import LOG as log + +class AlertManager(component.Component): + def __init__(self, session): + log.debug("AlertManager initialized..") + component.Component.__init__(self, "AlertManager", interval=50) + self.session = session + self.session.set_alert_mask( + lt.alert.category_t.error_notification | + lt.alert.category_t.port_mapping_notification | + lt.alert.category_t.storage_notification | + lt.alert.category_t.tracker_notification | + lt.alert.category_t.status_notification | + lt.alert.category_t.ip_block_notification) + + # handlers is a dictionary of lists {"alert_type": [handler1,h2,..]} + self.handlers = {} + + def update(self): + self.handle_alerts() + + def shutdown(self): + del self.session + del self.handlers + + def register_handler(self, alert_type, handler): + """Registers a function that will be called when 'alert_type' is pop'd + in handle_alerts. The handler function should look like: + handler(alert) + Where 'alert' is the actual alert object from libtorrent + """ + if alert_type not in self.handlers.keys(): + # There is no entry for this alert type yet, so lets make it with an + # empty list. + self.handlers[alert_type] = [] + + # Append the handler to the list in the handlers dictionary + self.handlers[alert_type].append(handler) + log.debug("Registered handler for alert %s", alert_type) + + def deregister_handler(self, handler): + """De-registers the 'handler' function from all alert types.""" + # Iterate through all handlers and remove 'handler' where found + for (key, value) in self.handlers: + if handler in value: + # Handler is in this alert type list + value.remove(handler) + + def handle_alerts(self, wait=False): + """Pops all libtorrent alerts in the session queue and handles them + appropriately.""" + alert = self.session.pop_alert() + while alert is not None: + # Loop through all alerts in the queue + # Do some magic to get the alert type as a string + alert_type = str(type(alert)).split("'")[1].split(".")[2] + # Display the alert message + log.debug("%s: %s", alert_type, alert.message()) + # Call any handlers for this alert type + if alert_type in self.handlers.keys(): + for handler in self.handlers[alert_type]: + if not wait: + gobject.idle_add(handler, alert) + else: + handler(alert) + + alert = self.session.pop_alert() + + # Return True so that the timer continues + return True diff --git a/deluge/core/autoadd.py b/deluge/core/autoadd.py new file mode 100644 index 000000000..213539203 --- /dev/null +++ b/deluge/core/autoadd.py @@ -0,0 +1,125 @@ +# +# autoadd.py +# +# Copyright (C) 2008 Andrew Resch ('andar') +# +# 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 2 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 os + +import deluge.libtorrent as lt +import deluge.component as component +from deluge.configmanager import ConfigManager +from deluge.log import LOG as log + +MAX_NUM_ATTEMPTS = 10 + +class AutoAdd(component.Component): + def __init__(self): + component.Component.__init__(self, "AutoAdd", depend=["TorrentManager"], interval=3000) + # Get the core config + self.config = ConfigManager("core.conf") + + # A list of filenames + self.invalid_torrents = [] + # Filename:Attempts + self.attempts = {} + + # Register set functions + self.config.register_set_function("autoadd_enable", + self._on_autoadd_enable, apply_now=True) + self.config.register_set_function("autoadd_location", + self._on_autoadd_location) + + def update(self): + if not self.config["autoadd_enable"]: + # We shouldn't be updating because autoadd is not enabled + component.pause("AutoAdd") + return + + # Check the auto add folder for new torrents to add + if not os.path.exists(self.config["autoadd_location"]): + log.warning("Invalid AutoAdd folder: %s", self.config["autoadd_location"]) + component.pause("AutoAdd") + return + + for filename in os.listdir(self.config["autoadd_location"]): + if filename.split(".")[-1] == "torrent": + filepath = os.path.join(self.config["autoadd_location"], filename) + try: + filedump = self.load_torrent(filepath) + except Exception, e: + # If the torrent is invalid, we keep track of it so that we + # can try again on the next pass. This is because some + # torrents may not be fully saved during the pass. + log.debug("Torrent is invalid: %s", e) + if filename in self.invalid_torrents: + self.attempts[filename] += 1 + if self.attempts[filename] >= MAX_NUM_ATTEMPTS: + os.rename(filepath, filepath + ".invalid") + del self.attempts[filename] + self.invalid_torrents.remove(filename) + else: + self.invalid_torrents.append(filename) + self.attempts[filename] = 1 + continue + + # The torrent looks good, so lets add it to the session + component.get("TorrentManager").add(filedump=filedump, filename=filename) + + os.remove(filepath) + + def load_torrent(self, filename): + try: + log.debug("Attempting to open %s for add.", filename) + _file = open(filename, "rb") + filedump = _file.read() + _file.close() + except IOError, e: + log.warning("Unable to open %s: %s", filename, e) + raise e + + # Get the info to see if any exceptions are raised + info = lt.torrent_info(lt.bdecode(filedump)) + + return filedump + + def _on_autoadd_enable(self, key, value): + log.debug("_on_autoadd_enable") + if value: + component.resume("AutoAdd") + else: + component.pause("AutoAdd") + + def _on_autoadd_location(self, key, value): + log.debug("_on_autoadd_location") + # We need to resume the component just incase it was paused due to + # an invalid autoadd location. + if self.config["autoadd_enable"]: + component.resume("AutoAdd") diff --git a/deluge/core/core.py b/deluge/core/core.py new file mode 100644 index 000000000..9643e5ad7 --- /dev/null +++ b/deluge/core/core.py @@ -0,0 +1,912 @@ +# +# core.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 gettext +import locale +import pkg_resources +import sys +import shutil +import os +import os.path +import signal +import deluge.SimpleXMLRPCServer as SimpleXMLRPCServer +from SocketServer import ThreadingMixIn +import deluge.xmlrpclib as xmlrpclib +import gobject +import threading +import socket + +import deluge.libtorrent as lt +import deluge.configmanager +import deluge.common +import deluge.component as component +from deluge.core.torrentmanager import TorrentManager +from deluge.core.pluginmanager import PluginManager +from deluge.core.alertmanager import AlertManager +from deluge.core.signalmanager import SignalManager +from deluge.core.autoadd import AutoAdd +from deluge.log import LOG as log + +DEFAULT_PREFS = { + "config_location": deluge.configmanager.get_config_dir(), + "send_info": False, + "info_sent": 0.0, + "daemon_port": 58846, + "allow_remote": False, + "compact_allocation": False, + "download_location": deluge.common.get_default_download_dir(), + "listen_ports": [6881, 6891], + "copy_torrent_file": False, + "torrentfiles_location": os.path.join(deluge.common.get_default_download_dir(), "torrentfiles"), + "plugins_location": os.path.join(deluge.configmanager.get_config_dir(), "plugins"), + "state_location": os.path.join(deluge.configmanager.get_config_dir(), "state"), + "prioritize_first_last_pieces": False, + "random_port": True, + "dht": True, + "upnp": True, + "natpmp": True, + "utpex": True, + "lsd": True, + "enc_in_policy": 1, + "enc_out_policy": 1, + "enc_level": 2, + "enc_prefer_rc4": True, + "max_connections_global": -1, + "max_upload_speed": -1.0, + "max_download_speed": -1.0, + "max_upload_slots_global": -1, + "max_connections_per_torrent": -1, + "max_upload_slots_per_torrent": -1, + "max_upload_speed_per_torrent": -1, + "max_download_speed_per_torrent": -1, + "enabled_plugins": [], + "autoadd_location": deluge.common.get_default_download_dir(), + "autoadd_enable": False, + "add_paused": False, + "max_active_seeding": 5, + "max_active_downloading": 3, + "max_active_limit": 8, + "dont_count_slow_torrents": False, + "queue_new_to_top": False, + "stop_seed_at_ratio": False, + "remove_seed_at_ratio": False, + "stop_seed_ratio": 2.00, + "share_ratio_limit": 2.00, + "seed_time_ratio_limit": 7.00, + "seed_time_limit": 180, + "auto_managed": True, + "move_completed": False, + "move_completed_path": deluge.common.get_default_download_dir(), + "new_release_check": True, +} + +class Core( + ThreadingMixIn, + SimpleXMLRPCServer.SimpleXMLRPCServer, + component.Component): + def __init__(self, port): + log.debug("Core init..") + component.Component.__init__(self, "Core") + self.client_address = None + + # Get config + self.config = deluge.configmanager.ConfigManager("core.conf", DEFAULT_PREFS) + + if port == None: + port = self.config["daemon_port"] + + if self.config["allow_remote"]: + hostname = "" + else: + hostname = "localhost" + + # Setup the xmlrpc server + try: + log.info("Starting XMLRPC server on port %s", port) + SimpleXMLRPCServer.SimpleXMLRPCServer.__init__( + self, (hostname, port), logRequests=False, allow_none=True) + except: + log.info("Daemon already running or port not available..") + sys.exit(0) + + self.register_multicall_functions() + + # Register all export_* functions + for func in dir(self): + if func.startswith("export_"): + self.register_function(getattr(self, "%s" % func), func[7:]) + + self.register_introspection_functions() + + # Initialize gettext + if deluge.common.windows_check(): + locale.setlocale(locale.LC_ALL, '') + else: + locale.setlocale(locale.LC_MESSAGES, '') + locale.bindtextdomain("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) + locale.textdomain("deluge") + + gettext.bindtextdomain("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) + gettext.textdomain("deluge") + gettext.install("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) + # Setup signals + try: + import gnome.ui + self.gnome_client = gnome.ui.Client() + self.gnome_client.connect("die", self._shutdown) + except: + pass + + signal.signal(signal.SIGINT, self._shutdown) + signal.signal(signal.SIGTERM, self._shutdown) + if not deluge.common.windows_check(): + signal.signal(signal.SIGHUP, self._shutdown) + else: + from win32api import SetConsoleCtrlHandler + from win32con import CTRL_CLOSE_EVENT + result = 0 + def win_handler(ctrl_type): + if ctrl_type == CTRL_CLOSE_EVENT: + self._shutdown() + result = 1 + return result + SetConsoleCtrlHandler(win_handler) + + def get_request(self): + """Get the request and client address from the socket. + We override this so that we can get the ip address of the client. + """ + request, client_address = self.socket.accept() + self.client_address = client_address[0] + return (request, client_address) + + def run(self): + """Starts the core""" + + # Create the client fingerprint + version = [] + for value in deluge.common.get_version().split("."): + version.append(int(value.split("-")[0])) + while len(version) < 4: + version.append(0) + fingerprint = lt.fingerprint("DE", *version) + + # Start the libtorrent session + log.debug("Starting libtorrent session..") + self.session = lt.session(fingerprint) + + # Set the user agent + self.settings = lt.session_settings() + self.settings.user_agent = "Deluge %s" % deluge.common.get_version() + + # Set lazy bitfield + self.settings.lazy_bitfields = 1 + self.session.set_settings(self.settings) + + # Load metadata extension + self.session.add_extension(lt.create_metadata_plugin) + + # Register set functions in the Config + self.config.register_set_function("torrentfiles_location", + self._on_set_torrentfiles_location) + self.config.register_set_function("state_location", + self._on_set_state_location) + self.config.register_set_function("listen_ports", + self._on_set_listen_ports) + self.config.register_set_function("random_port", + self._on_set_random_port) + self.config.register_set_function("dht", self._on_set_dht) + self.config.register_set_function("upnp", self._on_set_upnp) + self.config.register_set_function("natpmp", self._on_set_natpmp) + self.config.register_set_function("utpex", self._on_set_utpex) + self.config.register_set_function("lsd", self._on_set_lsd) + self.config.register_set_function("enc_in_policy", + self._on_set_encryption) + self.config.register_set_function("enc_out_policy", + self._on_set_encryption) + self.config.register_set_function("enc_level", + self._on_set_encryption) + self.config.register_set_function("enc_prefer_rc4", + self._on_set_encryption) + self.config.register_set_function("max_connections_global", + self._on_set_max_connections_global) + self.config.register_set_function("max_upload_speed", + self._on_set_max_upload_speed) + self.config.register_set_function("max_download_speed", + self._on_set_max_download_speed) + self.config.register_set_function("max_upload_slots_global", + self._on_set_max_upload_slots_global) + self.config.register_set_function("share_ratio_limit", + self._on_set_share_ratio_limit) + self.config.register_set_function("seed_time_ratio_limit", + self._on_set_seed_time_ratio_limit) + self.config.register_set_function("seed_time_limit", + self._on_set_seed_time_limit) + self.config.register_set_function("max_active_downloading", + self._on_set_max_active_downloading) + self.config.register_set_function("max_active_seeding", + self._on_set_max_active_seeding) + self.config.register_set_function("max_active_limit", + self._on_set_max_active_limit) + self.config.register_set_function("dont_count_slow_torrents", + self._on_set_dont_count_slow_torrents) + self.config.register_set_function("send_info", + self._on_send_info) + self.new_release = None + self.new_release_timer = None + self.config.register_set_function("new_release_check", + self._on_new_release_check) + + self.config.register_change_callback(self._on_config_value_change) + # Start the AlertManager + self.alerts = AlertManager(self.session) + + # Start the SignalManager + self.signals = SignalManager() + + # Load plugins + self.plugins = PluginManager(self) + + # Start the TorrentManager + self.torrents = TorrentManager(self.session, self.alerts) + + # Create the AutoAdd component + self.autoadd = AutoAdd() + + component.start() + + self._should_shutdown = False + + self.listen_thread = threading.Thread(target=self.handle_thread) + self.listen_thread.setDaemon(False) + self.listen_thread.start() + gobject.threads_init() + + self.loop = gobject.MainLoop() + try: + self.loop.run() + except KeyboardInterrupt: + self._shutdown() + + def handle_thread(self): + try: + while not self._should_shutdown: + self.handle_request() + self._should_shutdown = False + + except Exception, e: + log.debug("handle_thread: %s", e) + + def _shutdown(self, *data): + """This is called by a thread from shutdown()""" + log.info("Shutting down core..") + self._should_shutdown = True + # Shutdown the socket + try: + self.socket.shutdown(socket.SHUT_RDWR) + except Exception, e: + log.debug("exception in socket shutdown: %s", e) + log.debug("Joining listen thread to make sure it shutdowns cleanly..") + # Join the listen thread for a maximum of 1 second + self.listen_thread.join(1.0) + + # Start shutting down the components + component.shutdown() + + # Make sure the config file has been saved + self.config.save() + del self.config + del deluge.configmanager + del self.session + self.loop.quit() + try: + self.gnome_client.disconnect() + except: + pass + + # Exported Methods + def export_ping(self): + """A method to see if the core is running""" + return True + + def export_shutdown(self): + """Shutdown the core""" + # Make shutdown an async call + gobject.idle_add(self._shutdown) + + def export_register_client(self, port): + """Registers a client with the signal manager so that signals are + sent to it.""" + self.signals.register_client(self.client_address, port) + if self.config["new_release_check"]: + self.check_new_release() + + def export_deregister_client(self): + """De-registers a client with the signal manager.""" + self.signals.deregister_client(self.client_address) + + def export_add_torrent_file(self, filename, filedump, options): + """Adds a torrent file to the libtorrent session + This requires the torrents filename and a dump of it's content + """ + gobject.idle_add(self._add_torrent_file, filename, filedump, options) + + def _add_torrent_file(self, filename, filedump, options): + # Turn the filedump into a torrent_info + if not isinstance(filedump, str): + filedump = filedump.data + + if len(filedump) == 0: + log.warning("Torrent file is corrupt!") + return + + try: + torrent_info = lt.torrent_info(lt.bdecode(filedump)) + except RuntimeError, e: + log.warning("Unable to decode torrent file: %s", e) + return None + + torrent_id = self.torrents.add(filedump=filedump, options=options, filename=filename) + + # Run the plugin hooks for 'post_torrent_add' + self.plugins.run_post_torrent_add(torrent_id) + + def export_add_torrent_url(self, url, save_path, options): + log.info("Attempting to add url %s", url) + + # Get the actual filename of the torrent from the url provided. + filename = url.split("/")[-1] + + # Get the .torrent file from the url + torrent_file = deluge.common.fetch_url(url) + if torrent_file is None: + return False + + # Dump the torrents file contents to a string + try: + filedump = open(torrent_file, "rb").read() + except IOError: + log.warning("Unable to open %s for reading.", torrent_file) + return False + + # Add the torrent to session + return self.export_add_torrent_file( + filename, filedump, options) + + def export_remove_torrent(self, torrent_ids, remove_torrent, remove_data): + log.debug("Removing torrent %s from the core.", torrent_ids) + for torrent_id in torrent_ids: + if self.torrents.remove(torrent_id, remove_torrent, remove_data): + # Run the plugin hooks for 'post_torrent_remove' + self.plugins.run_post_torrent_remove(torrent_id) + # Emit the torrent_removed signal + self.torrent_removed(torrent_id) + + def export_force_reannounce(self, torrent_ids): + log.debug("Forcing reannouncment to: %s", torrent_ids) + for torrent_id in torrent_ids: + self.torrents[torrent_id].force_reannounce() + + def export_pause_torrent(self, torrent_ids): + log.debug("Pausing: %s", torrent_ids) + for torrent_id in torrent_ids: + if not self.torrents[torrent_id].pause(): + log.warning("Error pausing torrent %s", torrent_id) + + def export_move_storage(self, torrent_ids, dest): + log.debug("Moving storage %s to %s", torrent_ids, dest) + for torrent_id in torrent_ids: + if not self.torrents[torrent_id].move_storage(dest): + log.warning("Error moving torrent %s to %s", torrent_id, dest) + + def export_pause_all_torrents(self): + """Pause all torrents in the session""" + if not self.torrents.pause_all(): + log.warning("Error pausing all torrents..") + + def export_resume_all_torrents(self): + """Resume all torrents in the session""" + if self.torrents.resume_all(): + # Emit the 'torrent_all_resumed' signal + self.torrent_all_resumed() + + def export_resume_torrent(self, torrent_ids): + log.debug("Resuming: %s", torrent_ids) + for torrent_id in torrent_ids: + if self.torrents[torrent_id].resume(): + self.torrent_resumed(torrent_id) + + def export_get_torrent_status(self, torrent_id, keys): + # Build the status dictionary + try: + status = self.torrents[torrent_id].get_status(keys) + except KeyError: + # The torrent_id is not found in the torrentmanager, so return None + return None + + # Get the leftover fields and ask the plugin manager to fill them + leftover_fields = list(set(keys) - set(status.keys())) + if len(leftover_fields) > 0: + status.update(self.plugins.get_status(torrent_id, leftover_fields)) + return status + + def export_get_torrents_status(self, torrent_ids, keys): + status_dict = {}.fromkeys(torrent_ids) + + # Get the torrent status for each torrent_id + for torrent_id in torrent_ids: + try: + status = self.torrents[torrent_id].get_status(keys) + except KeyError: + return None + # Get the leftover fields and ask the plugin manager to fill them + leftover_fields = list(set(keys) - set(status.keys())) + if len(leftover_fields) > 0: + status.update( + self.plugins.get_status(torrent_id, leftover_fields)) + + status_dict[torrent_id] = status + # Emit the torrent_status signal to the clients + return status_dict + + def export_get_session_state(self): + """Returns a list of torrent_ids in the session.""" + # Get the torrent list from the TorrentManager + return self.torrents.get_torrent_list() + + def export_save_state(self): + """Save the current session state to file.""" + # Have the TorrentManager save it's state + self.torrents.save_state() + + def export_get_config(self): + """Get all the preferences as a dictionary""" + return self.config.get_config() + + def export_get_config_value(self, key): + """Get the config value for key""" + try: + value = self.config[key] + except KeyError: + return None + + return value + + def export_set_config(self, config): + """Set the config with values from dictionary""" + config = deluge.common.pythonize(config) + # Load all the values into the configuration + for key in config.keys(): + self.config[key] = config[key] + + def export_get_listen_port(self): + """Returns the active listen port""" + return self.session.listen_port() + + def export_get_num_connections(self): + """Returns the current number of connections""" + return self.session.num_connections() + + def export_get_dht_nodes(self): + """Returns the number of dht nodes""" + return self.session.status().dht_nodes + + def export_get_download_rate(self): + """Returns the payload download rate""" + return self.session.status().payload_download_rate + + def export_get_upload_rate(self): + """Returns the payload upload rate""" + return self.session.status().payload_upload_rate + + def export_get_available_plugins(self): + """Returns a list of plugins available in the core""" + return self.plugins.get_available_plugins() + + def export_get_enabled_plugins(self): + """Returns a list of enabled plugins in the core""" + return self.plugins.get_enabled_plugins() + + def export_enable_plugin(self, plugin): + self.plugins.enable_plugin(plugin) + return None + + def export_disable_plugin(self, plugin): + self.plugins.disable_plugin(plugin) + return None + + def export_force_recheck(self, torrent_ids): + """Forces a data recheck on torrent_ids""" + for torrent_id in torrent_ids: + self.torrents[torrent_id].force_recheck() + + def export_set_torrent_trackers(self, torrent_id, trackers): + """Sets a torrents tracker list. trackers will be [{"url", "tier"}]""" + return self.torrents[torrent_id].set_trackers(trackers) + + def export_set_torrent_max_connections(self, torrent_id, value): + """Sets a torrents max number of connections""" + return self.torrents[torrent_id].set_max_connections(value) + + def export_set_torrent_max_upload_slots(self, torrent_id, value): + """Sets a torrents max number of upload slots""" + return self.torrents[torrent_id].set_max_upload_slots(value) + + def export_set_torrent_max_upload_speed(self, torrent_id, value): + """Sets a torrents max upload speed""" + return self.torrents[torrent_id].set_max_upload_speed(value) + + def export_set_torrent_max_download_speed(self, torrent_id, value): + """Sets a torrents max download speed""" + return self.torrents[torrent_id].set_max_download_speed(value) + + def export_set_torrent_file_priorities(self, torrent_id, priorities): + """Sets a torrents file priorities""" + return self.torrents[torrent_id].set_file_priorities(priorities) + + def export_set_torrent_prioritize_first_last(self, torrent_id, value): + """Sets a higher priority to the first and last pieces""" + return self.torrents[torrent_id].set_prioritize_first_last(value) + + def export_set_torrent_auto_managed(self, torrent_id, value): + """Sets the auto managed flag for queueing purposes""" + return self.torrents[torrent_id].set_auto_managed(value) + + def export_set_torrent_stop_at_ratio(self, torrent_id, value): + """Sets the torrent to stop at 'stop_ratio'""" + return self.torrents[torrent_id].set_stop_at_ratio(value) + + def export_set_torrent_stop_ratio(self, torrent_id, value): + """Sets the ratio when to stop a torrent if 'stop_at_ratio' is set""" + return self.torrents[torrent_id].set_stop_ratio(value) + + def export_set_torrent_remove_at_ratio(self, torrent_id, value): + """Sets the torrent to be removed at 'stop_ratio'""" + return self.torrents[torrent_id].set_remove_at_ratio(value) + + def export_block_ip_range(self, range): + """Block an ip range""" + try: + self.ip_filter.add_rule(range[0], range[1], 1) + except AttributeError: + self.export_reset_ip_filter() + self.ip_filter.add_rule(range[0], range[1], 1) + + def export_reset_ip_filter(self): + """Clears the ip filter""" + self.ip_filter = lt.ip_filter() + self.session.set_ip_filter(self.ip_filter) + + def export_get_health(self): + """Returns True if we have established incoming connections""" + return self.session.status().has_incoming_connections + + ## Queueing functions ## + def export_queue_top(self, torrent_ids): + log.debug("Attempting to queue %s to top", torrent_ids) + for torrent_id in torrent_ids: + try: + # If the queue method returns True, then we should emit a signal + if self.torrents.queue_top(torrent_id): + self._torrent_queue_changed() + except KeyError: + log.warning("torrent_id: %s does not exist in the queue", torrent_id) + + def export_queue_up(self, torrent_ids): + log.debug("Attempting to queue %s to up", torrent_ids) + #torrent_ids must be sorted before moving. + torrent_ids.sort(key = lambda id: self.torrents.torrents[id].get_queue_position()) + for torrent_id in torrent_ids: + try: + # If the queue method returns True, then we should emit a signal + if self.torrents.queue_up(torrent_id): + self._torrent_queue_changed() + except KeyError: + log.warning("torrent_id: %s does not exist in the queue", torrent_id) + + def export_queue_down(self, torrent_ids): + log.debug("Attempting to queue %s to down", torrent_ids) + #torrent_ids must be sorted before moving. + torrent_ids.sort(key = lambda id: -self.torrents.torrents[id].get_queue_position()) + for torrent_id in torrent_ids: + try: + # If the queue method returns True, then we should emit a signal + if self.torrents.queue_down(torrent_id): + self._torrent_queue_changed() + except KeyError: + log.warning("torrent_id: %s does not exist in the queue", torrent_id) + + def export_queue_bottom(self, torrent_ids): + log.debug("Attempting to queue %s to bottom", torrent_ids) + for torrent_id in torrent_ids: + try: + # If the queue method returns True, then we should emit a signal + if self.torrents.queue_bottom(torrent_id): + self._torrent_queue_changed() + except KeyError: + log.warning("torrent_id: %s does not exist in the queue", torrent_id) + + # Signals + def torrent_removed(self, torrent_id): + """Emitted when a torrent has been removed from the core""" + log.debug("torrent_remove signal emitted") + self.signals.emit("torrent_removed", torrent_id) + + def torrent_paused(self, torrent_id): + """Emitted when a torrent is paused""" + log.debug("torrent_paused signal emitted") + self.signals.emit("torrent_paused", torrent_id) + + def torrent_resumed(self, torrent_id): + """Emitted when a torrent is resumed""" + log.debug("torrent_resumed signal emitted") + self.signals.emit("torrent_resumed", torrent_id) + + def torrent_all_paused(self): + """Emitted when all torrents have been paused""" + log.debug("torrent_all_paused signal emitted") + self.signals.emit("torrent_all_paused") + + def torrent_all_resumed(self): + """Emitted when all torrents have been resumed""" + log.debug("torrent_all_resumed signal emitted") + self.signals.emit("torrent_all_resumed") + + def config_value_changed(self, key, value): + """Emitted when a config value has changed""" + log.debug("config_value_changed signal emitted") + self.signals.emit("config_value_changed", key, value) + + def _torrent_queue_changed(self): + """Emitted when a torrent queue position is changed""" + log.debug("torrent_queue_changed signal emitted") + self.signals.emit("torrent_queue_changed") + + # Config set functions + def _on_config_value_change(self, key, value): + self.config_value_changed(key, value) + + def _on_set_torrentfiles_location(self, key, value): + # First try to create the new directory + try: + os.makedirs(value) + except Exception, e: + log.debug("Unable to make directory: %s", e) + + def _on_set_state_location(self, key, value): + if not os.access(value, os.F_OK): + try: + os.makedirs(value) + except Exception, e: + log.debug("Unable to make directory: %s", e) + + def _on_set_listen_ports(self, key, value): + # Only set the listen ports if random_port is not true + if self.config["random_port"] is not True: + log.debug("listen port range set to %s-%s", value[0], value[1]) + self.session.listen_on(value[0], value[1]) + + def _on_set_random_port(self, key, value): + log.debug("random port value set to %s", value) + # We need to check if the value has been changed to true and false + # and then handle accordingly. + if value: + import random + listen_ports = [] + randrange = lambda: random.randrange(49152, 65525) + listen_ports.append(randrange()) + listen_ports.append(listen_ports[0]+10) + else: + listen_ports = self.config["listen_ports"] + + # Set the listen ports + log.debug("listen port range set to %s-%s", listen_ports[0], + listen_ports[1]) + self.session.listen_on(listen_ports[0], listen_ports[1]) + + def _on_set_dht(self, key, value): + log.debug("dht value set to %s", value) + if value: + self.session.start_dht(None) + self.session.add_dht_router("router.bittorrent.com", 6881) + self.session.add_dht_router("router.utorrent.com", 6881) + self.session.add_dht_router("router.bitcomet.com", 6881) + else: + self.session.stop_dht() + + def _on_set_upnp(self, key, value): + log.debug("upnp value set to %s", value) + if value: + self.session.start_upnp() + else: + self.session.stop_upnp() + + def _on_set_natpmp(self, key, value): + log.debug("natpmp value set to %s", value) + if value: + self.session.start_natpmp() + else: + self.session.stop_natpmp() + + def _on_set_lsd(self, key, value): + log.debug("lsd value set to %s", value) + if value: + self.session.start_lsd() + else: + self.session.stop_lsd() + + def _on_set_utpex(self, key, value): + log.debug("utpex value set to %s", value) + if value: + self.session.add_extension(lt.create_ut_pex_plugin) + + def _on_set_encryption(self, key, value): + log.debug("encryption value %s set to %s..", key, value) + pe_settings = lt.pe_settings() + pe_settings.out_enc_policy = \ + lt.enc_policy(self.config["enc_out_policy"]) + pe_settings.in_enc_policy = lt.enc_policy(self.config["enc_in_policy"]) + pe_settings.allowed_enc_level = lt.enc_level(self.config["enc_level"]) + pe_settings.prefer_rc4 = self.config["enc_prefer_rc4"] + self.session.set_pe_settings(pe_settings) + set = self.session.get_pe_settings() + log.debug("encryption settings:\n\t\t\tout_policy: %s\n\t\t\ + in_policy: %s\n\t\t\tlevel: %s\n\t\t\tprefer_rc4: %s", + set.out_enc_policy, + set.in_enc_policy, + set.allowed_enc_level, + set.prefer_rc4) + + def _on_set_max_connections_global(self, key, value): + log.debug("max_connections_global set to %s..", value) + self.session.set_max_connections(value) + + def _on_set_max_upload_speed(self, key, value): + log.debug("max_upload_speed set to %s..", value) + # We need to convert Kb/s to B/s + self.session.set_upload_rate_limit(int(value * 1024)) + + def _on_set_max_download_speed(self, key, value): + log.debug("max_download_speed set to %s..", value) + # We need to convert Kb/s to B/s + self.session.set_download_rate_limit(int(value * 1024)) + + def _on_set_max_upload_slots_global(self, key, value): + log.debug("max_upload_slots_global set to %s..", value) + self.session.set_max_uploads(value) + + def _on_set_share_ratio_limit(self, key, value): + log.debug("%s set to %s..", key, value) + self.settings.share_ratio_limit = value + self.session.set_settings(self.settings) + + def _on_set_seed_time_ratio_limit(self, key, value): + log.debug("%s set to %s..", key, value) + self.settings.seed_time_ratio_limit = value + self.session.set_settings(self.settings) + + def _on_set_seed_time_limit(self, key, value): + log.debug("%s set to %s..", key, value) + # This value is stored in minutes in deluge, but libtorrent wants seconds + self.settings.seed_time_limit = int(value * 60) + self.session.set_settings(self.settings) + + def _on_set_max_active_downloading(self, key, value): + log.debug("%s set to %s..", key, value) + log.debug("active_downloads: %s", self.settings.active_downloads) + self.settings.active_downloads = value + self.session.set_settings(self.settings) + + def _on_set_max_active_seeding(self, key, value): + log.debug("%s set to %s..", key, value) + log.debug("active_seeds: %s", self.settings.active_seeds) + self.settings.active_seeds = value + self.session.set_settings(self.settings) + + def _on_set_max_active_limit(self, key, value): + log.debug("%s set to %s..", key, value) + log.debug("active_limit: %s", self.settings.active_limit) + self.settings.active_limit = value + self.session.set_settings(self.settings) + + def _on_set_dont_count_slow_torrents(self, key, value): + log.debug("%s set to %s..", key, value) + self.settings.dont_count_slow_torrents = value + self.session.set_settings(self.settings) + + def _on_send_info(self, key, value): + log.debug("Sending anonymous stats..") + """sends anonymous stats home""" + class Send_Info_Thread(threading.Thread): + def __init__(self, config): + self.config = config + threading.Thread.__init__(self) + def run(self): + import time + now = time.time() + # check if we've done this within the last week or never + if (now - self.config["info_sent"]) >= (60 * 60 * 24 * 7): + import deluge.common + import urllib + import platform + try: + url = "http://deluge-torrent.org/stats_get.php?processor=" + \ + platform.machine() + "&python=" + platform.python_version() \ + + "&deluge=" + deluge.common.get_version() \ + + "&os=" + platform.system() \ + + "&plugins=" + urllib.quote_plus(self.config["enabled_plugins"]) + urllib.urlopen(url) + except IOError, e: + log.debug("Network error while trying to send info: %s", e) + else: + self.config["info_sent"] = now + if value: + Send_Info_Thread(self.config).start() + + def get_new_release(self): + log.debug("get_new_release") + import urllib + try: + self.new_release = urllib.urlopen( + "http://download.deluge-torrent.org/version-1.0").read().strip() + except Exception, e: + log.debug("Unable to get release info from website: %s", e) + return + self.check_new_release() + + def check_new_release(self): + if self.new_release: + log.debug("new_release: %s", self.new_release) + if self.new_release > deluge.common.get_version(): + self.signals.emit("new_version_available", self.new_release) + return self.new_release + return False + + def _on_new_release_check(self, key, value): + if value: + log.debug("Checking for new release..") + threading.Thread(target=self.get_new_release).start() + if self.new_release_timer: + gobject.source_remove(self.new_release_timer) + # Set a timer to check for a new release every 3 days + self.new_release_timer = gobject.timeout_add( + 72 * 60 * 60 * 1000, self._on_new_release_check, "new_release_check", True) + else: + if self.new_release_timer: + gobject.source.remove(self.new_release_timer) diff --git a/deluge/core/daemon.py b/deluge/core/daemon.py new file mode 100644 index 000000000..e1196ad09 --- /dev/null +++ b/deluge/core/daemon.py @@ -0,0 +1,53 @@ +# +# daemon.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 deluge.configmanager +import deluge.common +from deluge.log import LOG as log + +class Daemon: + def __init__(self, options, args): + version = deluge.common.get_version() + if deluge.common.get_revision() != "": + version = version + "r" + deluge.common.get_revision() + + log.info("Deluge daemon %s", version) + log.debug("options: %s", options) + log.debug("args: %s", args) + # Set the config directory + deluge.configmanager.set_config_dir(options.config) + + from deluge.core.core import Core + # Start the core as a thread and join it until it's done + self.core = Core(options.port).run() + diff --git a/deluge/core/pluginmanager.py b/deluge/core/pluginmanager.py new file mode 100644 index 000000000..8c80f6ba4 --- /dev/null +++ b/deluge/core/pluginmanager.py @@ -0,0 +1,162 @@ +# +# pluginmanager.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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. + +"""PluginManager for Core""" + +import gobject + +import deluge.pluginmanagerbase +import deluge.component as component +from deluge.log import LOG as log + +class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, + component.Component): + """PluginManager handles the loading of plugins and provides plugins with + functions to access parts of the core.""" + + def __init__(self, core): + component.Component.__init__(self, "PluginManager") + self.core = core + # Set up the hooks dictionary + self.hooks = { + "post_torrent_add": [], + "post_torrent_remove": [], + "post_session_load": [] + } + + self.status_fields = {} + + # Call the PluginManagerBase constructor + deluge.pluginmanagerbase.PluginManagerBase.__init__( + self, "core.conf", "deluge.plugin.core") + + def start(self): + # Enable plugins that are enabled in the config + self.enable_plugins() + + # Set update timer to call update() in plugins every second + self.update_timer = gobject.timeout_add(1000, self.update_plugins) + + def stop(self): + # Disable all enabled plugins + self.disable_plugins() + # Stop the update timer + gobject.source_remove(self.update_timer) + + def shutdown(self): + self.stop() + + def update_plugins(self): + for plugin in self.plugins.keys(): + try: + self.plugins[plugin].update() + except AttributeError: + # We don't care if this doesn't work + pass + + def get_core(self): + """Returns a reference to the core""" + return self.core + + def register_status_field(self, field, function): + """Register a new status field. This can be used in the same way the + client requests other status information from core.""" + log.debug("Registering status field %s with PluginManager", field) + self.status_fields[field] = function + + def deregister_status_field(self, field): + """Deregisters a status field""" + log.debug("Deregistering status field %s with PluginManager", field) + try: + del self.status_fields[field] + except: + log.warning("Unable to deregister status field %s", field) + + def get_status(self, torrent_id, fields): + """Return the value of status fields for the selected torrent_id.""" + status = {} + for field in fields: + try: + status[field] = self.status_fields[field](torrent_id) + except KeyError: + log.warning("Status field %s is not registered with the\ + PluginManager.", field) + return status + + def register_hook(self, hook, function): + """Register a hook function with the plugin manager""" + try: + self.hooks[hook].append(function) + except KeyError: + log.warning("Plugin attempting to register invalid hook.") + + def deregister_hook(self, hook, function): + """Deregisters a hook function""" + try: + self.hooks[hook].remove(function) + except: + log.warning("Unable to deregister hook %s", hook) + + def run_post_torrent_add(self, torrent_id): + """This hook is run after a torrent has been added to the session.""" + log.debug("run_post_torrent_add") + for function in self.hooks["post_torrent_add"]: + function(torrent_id) + + def run_post_torrent_remove(self, torrent_id): + """This hook is run after a torrent has been removed from the session. + """ + log.debug("run_post_torrent_remove") + for function in self.hooks["post_torrent_remove"]: + function(torrent_id) + + def run_post_session_load(self): + """This hook is run after all the torrents have been loaded into the + session from the saved state. It is called prior to resuming the + torrents and they all will have a 'Paused' state.""" + log.debug("run_post_session_load") + for function in self.hooks["post_session_load"]: + function() + + def get_torrent_list(self): + """Returns a list of torrent_id's in the current session.""" + return component.get("TorrentManager").get_torrent_list() + + def block_ip_range(self, range): + """Blocks the ip range in the core""" + return self.core.export_block_ip_range(range) + + def reset_ip_filter(self): + """Resets the ip filter""" + return self.core.export_reset_ip_filter() + diff --git a/deluge/core/signalmanager.py b/deluge/core/signalmanager.py new file mode 100644 index 000000000..92f6247a8 --- /dev/null +++ b/deluge/core/signalmanager.py @@ -0,0 +1,81 @@ +# +# signalmanager.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 deluge.xmlrpclib as xmlrpclib +import socket + +import gobject + +import deluge.component as component +from deluge.log import LOG as log + +class SignalManager(component.Component): + def __init__(self): + component.Component.__init__(self, "SignalManager") + self.clients = {} + + def shutdown(self): + self.clients = {} + + def deregister_client(self, address): + """Deregisters a client""" + log.debug("Deregistering %s as a signal reciever..", address) + for client in self.clients.keys(): + if client.split("//")[1].split(":")[0] == address: + del self.clients[client] + break + + def register_client(self, address, port): + """Registers a client to emit signals to.""" + uri = "http://" + str(address) + ":" + str(port) + log.debug("Registering %s as a signal reciever..", uri) + self.clients[uri] = xmlrpclib.ServerProxy(uri) + + def emit(self, signal, *data): + for uri in self.clients: + gobject.idle_add(self._emit, uri, signal, 1, *data) + + def _emit(self, uri, signal, count, *data): + if uri not in self.clients: + return + client = self.clients[uri] + try: + client.emit_signal(signal, *data) + except (socket.error, Exception), e: + log.warning("Unable to emit signal to client %s: %s (%d)", client, e, count) + if count < 30: + gobject.timeout_add(1000, self._emit, uri, signal, count + 1, *data) + else: + log.info("Removing %s because it couldn't be reached..", uri) + del self.clients[uri] + diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py new file mode 100644 index 000000000..448cf435f --- /dev/null +++ b/deluge/core/torrent.py @@ -0,0 +1,586 @@ +# +# torrent.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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. + +"""Internal Torrent class""" + +import os + +import deluge.libtorrent as lt +import deluge.common +import deluge.component as component +from deluge.configmanager import ConfigManager +from deluge.log import LOG as log +import deluge.xmlrpclib + +TORRENT_STATE = deluge.common.TORRENT_STATE + +class Torrent: + """Torrent holds information about torrents added to the libtorrent session. + """ + def __init__(self, handle, options, state=None, filename=None): + log.debug("Creating torrent object %s", str(handle.info_hash())) + # Get the core config + self.config = ConfigManager("core.conf") + + self.signals = component.get("SignalManager") + + # Set the libtorrent handle + self.handle = handle + # Set the torrent_id for this torrent + self.torrent_id = str(handle.info_hash()) + + # We store the filename just in case we need to make a copy of the torrentfile + self.filename = filename + + # Holds status info so that we don't need to keep getting it from lt + self.status = self.handle.status() + self.torrent_info = self.handle.get_torrent_info() + + # Files dictionary + self.files = self.get_files() + # Set the default file priorities to normal + self.file_priorities = [1]* len(self.files) + + # Default total_uploaded to 0, this may be changed by the state + self.total_uploaded = 0 + + # Set default auto_managed value + self.auto_managed = options["auto_managed"] + if not handle.is_paused(): + handle.auto_managed(self.auto_managed) + + # We need to keep track if the torrent is finished in the state to prevent + # some weird things on state load. + self.is_finished = False + + # Queueing options + self.stop_at_ratio = False + self.stop_ratio = 2.00 + self.remove_at_ratio = False + + # Load values from state if we have it + if state is not None: + # This is for saving the total uploaded between sessions + self.total_uploaded = state.total_uploaded + # Set the trackers + self.set_trackers(state.trackers) + # Set the filename + self.filename = state.filename + self.is_finished = state.is_finished + # Set the per-torrent queue options + self.set_stop_at_ratio(state.stop_at_ratio) + self.set_stop_ratio(state.stop_ratio) + self.set_remove_at_ratio(state.remove_at_ratio) + else: + # Tracker list + self.trackers = [] + # Create a list of trackers + for value in self.handle.trackers(): + tracker = {} + tracker["url"] = value.url + tracker["tier"] = value.tier + self.trackers.append(tracker) + + # Various torrent options + self.set_max_connections(options["max_connections_per_torrent"]) + self.set_max_upload_slots(options["max_upload_slots_per_torrent"]) + self.set_max_upload_speed(options["max_upload_speed_per_torrent"]) + self.set_max_download_speed(options["max_download_speed_per_torrent"]) + self.set_prioritize_first_last(options["prioritize_first_last_pieces"]) + self.handle.resolve_countries(True) + if options.has_key("file_priorities"): + self.set_file_priorities(options["file_priorities"]) + + # Set the allocation mode + self.compact = options["compact_allocation"] + # Where the torrent is being saved to + self.save_path = options["download_location"] + # Status message holds error info about the torrent + self.statusmsg = "OK" + + # The torrents state + self.update_state() + + # The tracker status + self.tracker_status = "" + + log.debug("Torrent object created.") + + def set_tracker_status(self, status): + """Sets the tracker status""" + self.tracker_status = status + + def set_max_connections(self, max_connections): + self.max_connections = int(max_connections) + self.handle.set_max_connections(self.max_connections) + + def set_max_upload_slots(self, max_slots): + self.max_upload_slots = int(max_slots) + self.handle.set_max_uploads(self.max_upload_slots) + + def set_max_upload_speed(self, m_up_speed): + self.max_upload_speed = m_up_speed + self.handle.set_upload_limit(int(m_up_speed * 1024)) + + def set_max_download_speed(self, m_down_speed): + self.max_download_speed = m_down_speed + self.handle.set_download_limit(int(m_down_speed * 1024)) + + def set_prioritize_first_last(self, prioritize): + self.prioritize_first_last = prioritize + if self.prioritize_first_last: + if self.handle.get_torrent_info().num_files() == 1: + # We only do this if one file is in the torrent + priorities = [1] * self.handle.get_torrent_info().num_pieces() + priorities[0] = 7 + priorities[-1] = 7 + self.handle.prioritize_pieces(priorities) + + def set_save_path(self, save_path): + self.save_path = save_path + + def set_auto_managed(self, auto_managed): + self.auto_managed = auto_managed + self.handle.auto_managed(auto_managed) + self.update_state() + + def set_stop_ratio(self, stop_ratio): + self.stop_ratio = stop_ratio + + def set_stop_at_ratio(self, stop_at_ratio): + self.stop_at_ratio = stop_at_ratio + + def set_remove_at_ratio(self, remove_at_ratio): + self.remove_at_ratio = remove_at_ratio + + def set_file_priorities(self, file_priorities): + log.debug("setting %s's file priorities: %s", self.torrent_id, file_priorities) + if len(file_priorities) != len(self.files): + log.debug("file_priorities len != num_files") + return + + self.handle.prioritize_files(file_priorities) + + if 0 in self.file_priorities: + # We have previously marked a file 'Do Not Download' + # Check to see if we have changed any 0's to >0 and change state accordingly + for index, priority in enumerate(self.file_priorities): + if priority == 0 and file_priorities[index] > 0: + # We have a changed 'Do Not Download' to a download priority + self.is_finished = False + self.update_state() + break + + self.file_priorities = file_priorities + + # Set the first/last priorities if needed + self.set_prioritize_first_last(self.prioritize_first_last) + + def set_trackers(self, trackers): + """Sets trackers""" + if trackers == None: + trackers = [] + + log.debug("Setting trackers for %s: %s", self.torrent_id, trackers) + tracker_list = [] + + for tracker in trackers: + new_entry = lt.announce_entry(tracker["url"]) + new_entry.tier = tracker["tier"] + tracker_list.append(new_entry) + + self.handle.replace_trackers(tracker_list) + + # Print out the trackers + for t in self.handle.trackers(): + log.debug("tier: %s tracker: %s", t.tier, t.url) + # Set the tracker list in the torrent object + self.trackers = trackers + if len(trackers) > 0: + # Force a reannounce if there is at least 1 tracker + self.force_reannounce() + + def update_state(self): + """Updates the state based on what libtorrent's state for the torrent is""" + # Set the initial state based on the lt state + LTSTATE = deluge.common.LT_TORRENT_STATE + ltstate = int(self.handle.status().state) + + log.debug("set_state_based_on_ltstate: %s", ltstate) + + if ltstate == LTSTATE["Queued"] or ltstate == LTSTATE["Checking"]: + self.state = "Checking" + return + elif ltstate == LTSTATE["Connecting"] or ltstate == LTSTATE["Downloading"] or\ + ltstate == LTSTATE["Downloading Metadata"]: + self.state = "Downloading" + elif ltstate == LTSTATE["Finished"] or ltstate == LTSTATE["Seeding"]: + self.state = "Seeding" + elif ltstate == LTSTATE["Allocating"]: + self.state = "Allocating" + + if self.handle.is_paused() and len(self.handle.status().error) > 0: + # This is an error'd torrent + self.state = "Error" + self.set_status_message(self.handle.status().error) + self.handle.auto_managed(False) + elif self.handle.is_paused() and self.handle.is_auto_managed(): + self.state = "Queued" + elif self.handle.is_paused() and not self.handle.is_auto_managed(): + self.state = "Paused" + + def set_state(self, state): + """Accepts state strings, ie, "Paused", "Seeding", etc.""" + if state not in TORRENT_STATE: + log.debug("Trying to set an invalid state %s", state) + return + + self.state = state + return + + def set_status_message(self, message): + self.statusmsg = message + + def get_eta(self): + """Returns the ETA in seconds for this torrent""" + if self.status == None: + status = self.handle.status() + else: + status = self.status + + left = status.total_wanted - status.total_done + + if left == 0 or status.download_payload_rate == 0: + return 0 + + try: + eta = left / status.download_payload_rate + except ZeroDivisionError: + eta = 0 + + return eta + + def get_ratio(self): + """Returns the ratio for this torrent""" + if self.status == None: + status = self.handle.status() + else: + status = self.status + + up = self.total_uploaded + status.total_payload_upload + down = status.total_done + + # Convert 'up' and 'down' to floats for proper calculation + up = float(up) + down = float(down) + + try: + ratio = up / down + except ZeroDivisionError: + return 0.0 + + return ratio + + def get_files(self): + """Returns a list of files this torrent contains""" + if self.torrent_info == None: + torrent_info = self.handle.get_torrent_info() + else: + torrent_info = self.torrent_info + + ret = [] + files = torrent_info.files() + for index, file in enumerate(files): + ret.append({ + 'index': index, + 'path': file.path, + 'size': file.size, + 'offset': file.offset + }) + return ret + + def get_peers(self): + """Returns a list of peers and various information about them""" + ret = [] + peers = self.handle.get_peer_info() + + for peer in peers: + # We do not want to report peers that are half-connected + if peer.flags & peer.connecting or peer.flags & peer.handshake: + continue + try: + client = str(peer.client).decode("utf-8") + except UnicodeDecodeError: + client = str(peer.client).decode("latin-1") + + # Make country a proper string + country = str() + for c in peer.country: + if not c.isalpha(): + country += " " + else: + country += c + + ret.append({ + "ip": "%s:%s" % (peer.ip[0], peer.ip[1]), + "up_speed": peer.up_speed, + "down_speed": peer.down_speed, + "country": country, + "client": client, + "seed": peer.flags & peer.seed + }) + + return ret + + def get_queue_position(self): + """Returns the torrents queue position""" + return self.handle.queue_position() + + def get_status(self, keys): + """Returns the status of the torrent based on the keys provided""" + # Create the full dictionary + self.status = self.handle.status() + self.torrent_info = self.handle.get_torrent_info() + + # Adjust progress to be 0-100 value + progress = self.status.progress * 100 + + # Adjust status.distributed_copies to return a non-negative value + distributed_copies = self.status.distributed_copies + if distributed_copies < 0: + distributed_copies = 0.0 + + full_status = { + "distributed_copies": distributed_copies, + "total_done": self.status.total_done, + "total_uploaded": self.total_uploaded + self.status.total_payload_upload, + "state": self.state, + "paused": self.status.paused, + "progress": progress, + "next_announce": self.status.next_announce.seconds, + "total_payload_download": self.status.total_payload_download, + "total_payload_upload": self.status.total_payload_upload, + "download_payload_rate": self.status.download_payload_rate, + "upload_payload_rate": self.status.upload_payload_rate, + "num_peers": self.status.num_peers - self.status.num_seeds, + "num_seeds": self.status.num_seeds, + "total_peers": self.status.num_incomplete, + "total_seeds": self.status.num_complete, + "total_wanted": self.status.total_wanted, + "tracker": self.status.current_tracker, + "trackers": self.trackers, + "tracker_status": self.tracker_status, + "save_path": self.save_path, + "files": self.files, + "file_priorities": self.file_priorities, + "compact": self.compact, + "max_connections": self.max_connections, + "max_upload_slots": self.max_upload_slots, + "max_upload_speed": self.max_upload_speed, + "max_download_speed": self.max_download_speed, + "prioritize_first_last": self.prioritize_first_last, + "message": self.statusmsg, + "hash": self.torrent_id, + "active_time": self.status.active_time, + "seeding_time": self.status.seeding_time, + "seed_rank": self.status.seed_rank, + "is_auto_managed": self.auto_managed, + "stop_ratio": self.stop_ratio, + "stop_at_ratio": self.stop_at_ratio, + "remove_at_ratio": self.remove_at_ratio + } + + fns = { + "name": self.torrent_info.name, + "private": self.torrent_info.priv, + "total_size": self.torrent_info.total_size, + "num_files": self.torrent_info.num_files, + "num_pieces": self.torrent_info.num_pieces, + "piece_length": self.torrent_info.piece_length, + "eta": self.get_eta, + "ratio": self.get_ratio, + "file_progress": self.handle.file_progress, + "queue": self.handle.queue_position, + "is_seed": self.handle.is_seed, + "peers": self.get_peers, + } + + self.status = None + self.torrent_info = None + + # Create the desired status dictionary and return it + status_dict = {} + + if len(keys) == 0: + status_dict = full_status + for key in fns: + status_dict[key] = fns[key]() + else: + for key in keys: + if key in full_status: + status_dict[key] = full_status[key] + elif key in fns: + status_dict[key] = fns[key]() + + return status_dict + + def apply_options(self): + """Applies the per-torrent options that are set.""" + self.handle.set_max_connections(self.max_connections) + self.handle.set_max_uploads(self.max_upload_slots) + self.handle.set_upload_limit(int(self.max_upload_speed * 1024)) + self.handle.set_download_limit(int(self.max_download_speed * 1024)) + self.handle.prioritize_files(self.file_priorities) + self.handle.resolve_countries(True) + + def pause(self): + """Pause this torrent""" + # Turn off auto-management so the torrent will not be unpaused by lt queueing + self.handle.auto_managed(False) + if self.handle.is_paused(): + # This torrent was probably paused due to being auto managed by lt + # Since we turned auto_managed off, we should update the state which should + # show it as 'Paused'. We need to emit a torrent_paused signal because + # the torrent_paused alert from libtorrent will not be generated. + self.update_state() + self.signals.emit("torrent_paused", self.torrent_id) + else: + try: + self.handle.pause() + except Exception, e: + log.debug("Unable to pause torrent: %s", e) + return False + + return True + + def resume(self): + """Resumes this torrent""" + + if self.handle.is_paused() and self.handle.is_auto_managed(): + log.debug("Torrent is being auto-managed, cannot resume!") + return + else: + # Reset the status message just in case of resuming an Error'd torrent + self.set_status_message("OK") + + if self.handle.is_finished(): + # If the torrent has already reached it's 'stop_seed_ratio' then do not do anything + if self.config["stop_seed_at_ratio"]: + if self.get_ratio() >= self.config["stop_seed_ratio"]: + self.signals.emit("torrent_resume_at_stop_ratio") + return + + if self.auto_managed: + # This torrent is to be auto-managed by lt queueing + self.handle.auto_managed(True) + + try: + self.handle.resume() + except: + pass + + return True + + def move_storage(self, dest): + """Move a torrent's storage location""" + try: + self.handle.move_storage(dest) + except: + return False + + return True + + def write_fastresume(self): + """Writes the .fastresume file for the torrent""" + resume_data = lt.bencode(self.handle.write_resume_data()) + path = "%s/%s.fastresume" % ( + self.config["state_location"], + self.torrent_id) + log.debug("Saving fastresume file: %s", path) + try: + fastresume = open(path, "wb") + fastresume.write(resume_data) + fastresume.close() + except IOError: + log.warning("Error trying to save fastresume file") + + def delete_fastresume(self): + """Deletes the .fastresume file""" + path = "%s/%s.fastresume" % ( + self.config["state_location"], + self.torrent_id) + log.debug("Deleting fastresume file: %s", path) + try: + os.remove(path) + except Exception, e: + log.warning("Unable to delete the fastresume file: %s", e) + + def delete_torrentfile(self): + """Deletes the .torrent file in the state""" + path = "%s/%s.torrent" % ( + self.config["state_location"], + self.torrent_id) + log.debug("Deleting torrent file: %s", path) + try: + os.remove(path) + except Exception, e: + log.warning("Unable to delete the torrent file: %s", e) + + def force_reannounce(self): + """Force a tracker reannounce""" + try: + self.handle.force_reannounce() + except Exception, e: + log.debug("Unable to force reannounce: %s", e) + return False + + return True + + def scrape_tracker(self): + """Scrape the tracker""" + try: + self.handle.scrape_tracker() + except Exception, e: + log.debug("Unable to scrape tracker: %s", e) + return False + + return True + + def force_recheck(self): + """Forces a recheck of the torrents pieces""" + try: + self.handle.force_recheck() + except Exception, e: + log.debug("Unable to force recheck: %s", e) + return False + return True diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py new file mode 100644 index 000000000..3174e3d6b --- /dev/null +++ b/deluge/core/torrentmanager.py @@ -0,0 +1,716 @@ +# +# torrentmanager.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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. + +"""TorrentManager handles Torrent objects""" + +import cPickle +import os.path +import os +import time + +import gobject + +import deluge.libtorrent as lt + +import deluge.common +import deluge.component as component +from deluge.configmanager import ConfigManager +from deluge.core.torrent import Torrent + +from deluge.log import LOG as log + +class TorrentState: + def __init__(self, + torrent_id=None, + filename=None, + total_uploaded=None, + trackers=None, + compact=None, + paused=None, + save_path=None, + max_connections=None, + max_upload_slots=None, + max_upload_speed=None, + max_download_speed=None, + prioritize_first_last=None, + file_priorities=None, + queue=None, + auto_managed=None, + is_finished=False, + stop_ratio=2.00, + stop_at_ratio=False, + remove_at_ratio=True + ): + self.torrent_id = torrent_id + self.filename = filename + self.total_uploaded = total_uploaded + self.trackers = trackers + self.queue = queue + self.is_finished = is_finished + + # Options + self.compact = compact + self.paused = paused + self.save_path = save_path + self.max_connections = max_connections + self.max_upload_slots = max_upload_slots + self.max_upload_speed = max_upload_speed + self.max_download_speed = max_download_speed + self.prioritize_first_last = prioritize_first_last + self.file_priorities = file_priorities + self.auto_managed = auto_managed + self.stop_ratio = stop_ratio + self.stop_at_ratio = stop_at_ratio + self.remove_at_ratio = remove_at_ratio + +class TorrentManagerState: + def __init__(self): + self.torrents = [] + +class TorrentManager(component.Component): + """TorrentManager contains a list of torrents in the current libtorrent + session. This object is also responsible for saving the state of the + session for use on restart.""" + + def __init__(self, session, alerts): + component.Component.__init__(self, "TorrentManager", interval=5000, depend=["PluginManager"]) + log.debug("TorrentManager init..") + # Set the libtorrent session + self.session = session + # Set the alertmanager + self.alerts = alerts + # Get the core config + self.config = ConfigManager("core.conf") + + # Create the torrents dict { torrent_id: Torrent } + self.torrents = {} + + # This is a list of torrent_id when we shutdown the torrentmanager. + # We use this list to determine if all active torrents have been paused + # and that their resume data has been written. + self.shutdown_torrent_pause_list = [] + + # Register set functions + self.config.register_set_function("max_connections_per_torrent", + self.on_set_max_connections_per_torrent) + self.config.register_set_function("max_upload_slots_per_torrent", + self.on_set_max_upload_slots_per_torrent) + self.config.register_set_function("max_upload_speed_per_torrent", + self.on_set_max_upload_speed_per_torrent) + self.config.register_set_function("max_download_speed_per_torrent", + self.on_set_max_download_speed_per_torrent) + + # Register alert functions + self.alerts.register_handler("torrent_finished_alert", + self.on_alert_torrent_finished) + self.alerts.register_handler("torrent_paused_alert", + self.on_alert_torrent_paused) + self.alerts.register_handler("torrent_checked_alert", + self.on_alert_torrent_checked) + self.alerts.register_handler("tracker_reply_alert", + self.on_alert_tracker_reply) + self.alerts.register_handler("tracker_announce_alert", + self.on_alert_tracker_announce) + self.alerts.register_handler("tracker_alert", self.on_alert_tracker) + self.alerts.register_handler("tracker_warning_alert", + self.on_alert_tracker_warning) + self.alerts.register_handler("storage_moved_alert", + self.on_alert_storage_moved) + self.alerts.register_handler("torrent_resumed_alert", + self.on_alert_torrent_resumed) + self.alerts.register_handler("state_changed_alert", + self.on_alert_state_changed) + + def start(self): + # Get the pluginmanager reference + self.plugins = component.get("PluginManager") + + self.signals = component.get("SignalManager") + + # Try to load the state from file + self.load_state() + + # Save the state every 5 minutes + self.save_state_timer = gobject.timeout_add(300000, self.save_state) + + def stop(self): + # Save state on shutdown + self.save_state() + + component.pause("AlertManager") + for key in self.torrents.keys(): + if not self.torrents[key].handle.is_paused(): + # We set auto_managed false to prevent lt from resuming the torrent + self.torrents[key].handle.auto_managed(False) + self.torrents[key].handle.pause() + self.shutdown_torrent_pause_list.append(key) + while self.shutdown_torrent_pause_list: + time.sleep(0.1) + # Wait for all alerts + self.alerts.handle_alerts(True) + + def update(self): + for torrent in self.torrents: + if self.config["stop_seed_at_ratio"] or torrent.stop_at_ratio: + if (torrent.get_ratio() >= self.config["stop_seed_ratio"] or\ + torrent.get_ratio() > torrent.stop_ratio) and torrent.is_finished: + torrent.pause() + if self.config["remove_seed_at_ratio"] or torrent.remove_at_ratio: + self.remove(torrent.torrent_id) + + def __getitem__(self, torrent_id): + """Return the Torrent with torrent_id""" + return self.torrents[torrent_id] + + def get_torrent_list(self): + """Returns a list of torrent_ids""" + return self.torrents.keys() + + def get_torrent_info_from_file(self, filepath): + """Returns a torrent_info for the file specified or None""" + torrent_info = None + # Get the torrent data from the torrent file + try: + log.debug("Attempting to create torrent_info from %s", filepath) + _file = open(filepath, "rb") + torrent_info = lt.torrent_info(lt.bdecode(_file.read())) + _file.close() + except (IOError, RuntimeError), e: + log.warning("Unable to open %s: %s", filepath, e) + + return torrent_info + + def get_resume_data_from_file(self, torrent_id): + """Returns an entry with the resume data or None""" + fastresume = None + try: + _file = open( + os.path.join( + self.config["state_location"], + torrent_id + ".fastresume"), + "rb") + fastresume = _file.read() + _file.close() + except IOError, e: + log.debug("Unable to load .fastresume: %s", e) + + return str(fastresume) + + def add(self, torrent_info=None, state=None, options=None, save_state=True, + filedump=None, filename=None): + """Add a torrent to the manager and returns it's torrent_id""" + + if torrent_info is None and state is None and filedump is None: + log.debug("You must specify a valid torrent_info or a torrent state object!") + return + + log.debug("torrentmanager.add") + add_torrent_params = {} + + if filedump is not None: + try: + torrent_info = lt.torrent_info(lt.bdecode(filedump)) + except Exception, e: + log.error("Unable to decode torrent file!: %s", e) + + if torrent_info is None: + # We have no torrent_info so we need to add the torrent with information + # from the state object. + + # Populate the options dict from state + options = {} + options["max_connections_per_torrent"] = state.max_connections + options["max_upload_slots_per_torrent"] = state.max_upload_slots + options["max_upload_speed_per_torrent"] = state.max_upload_speed + options["max_download_speed_per_torrent"] = state.max_download_speed + options["prioritize_first_last_pieces"] = state.prioritize_first_last + options["file_priorities"] = state.file_priorities + options["compact_allocation"] = state.compact + options["download_location"] = state.save_path + options["auto_managed"] = state.auto_managed + options["add_paused"] = state.paused + + add_torrent_params["ti"] =\ + self.get_torrent_info_from_file( + os.path.join(self.config["state_location"], state.torrent_id + ".torrent")) + if not add_torrent_params["ti"]: + log.error("Unable to add torrent!") + return + + add_torrent_params["resume_data"] = self.get_resume_data_from_file(state.torrent_id) + else: + # We have a torrent_info object so we're not loading from state. + # Check if options is None and load defaults + options_keys = [ + "compact_allocation", + "max_connections_per_torrent", + "max_upload_slots_per_torrent", + "max_upload_speed_per_torrent", + "max_download_speed_per_torrent", + "prioritize_first_last_pieces", + "download_location", + "add_paused", + "auto_managed" + ] + + if options == None: + options = {} + for key in options_keys: + options[key] = self.config[key] + else: + for key in options_keys: + if not options.has_key(key): + options[key] = self.config[key] + + add_torrent_params["ti"] = torrent_info + add_torrent_params["resume_data"] = "" + + #log.info("Adding torrent: %s", filename) + log.debug("options: %s", options) + + # Set the right storage_mode + if options["compact_allocation"]: + storage_mode = lt.storage_mode_t(2) + else: + storage_mode = lt.storage_mode_t(1) + + # Fill in the rest of the add_torrent_params dictionary + add_torrent_params["save_path"] = str(options["download_location"]) + + add_torrent_params["storage_mode"] = storage_mode + add_torrent_params["paused"] = True + add_torrent_params["auto_managed"] = False + add_torrent_params["duplicate_is_error"] = True + + # We need to pause the AlertManager momentarily to prevent alerts + # for this torrent being generated before a Torrent object is created. + component.pause("AlertManager") + + handle = None + try: + handle = self.session.add_torrent(add_torrent_params) + except RuntimeError, e: + log.warning("Error adding torrent: %s", e) + + if not handle or not handle.is_valid(): + log.debug("torrent handle is invalid!") + # The torrent was not added to the session + component.resume("AlertManager") + return + + log.debug("handle id: %s", str(handle.info_hash())) + # Create a Torrent object + torrent = Torrent(handle, options, state, filename) + # Add the torrent object to the dictionary + self.torrents[torrent.torrent_id] = torrent + if self.config["queue_new_to_top"]: + handle.queue_position_top() + + component.resume("AlertManager") + + # Resume the torrent if needed + if not options["add_paused"]: + handle.resume() + handle.auto_managed(options["auto_managed"]) + + # Write the .torrent file to the state directory + if filedump: + try: + save_file = open(os.path.join(self.config["state_location"], + torrent.torrent_id + ".torrent"), + "wb") + save_file.write(filedump) + save_file.close() + except IOError, e: + log.warning("Unable to save torrent file: %s", e) + + # If the user has requested a copy of the torrent be saved elsewhere + # we need to do that. + if self.config["copy_torrent_file"] and filename is not None: + try: + save_file = open( + os.path.join(self.config["torrentfiles_location"], filename), + "wb") + save_file.write(filedump) + save_file.close() + except IOError, e: + log.warning("Unable to save torrent file: %s", e) + + if save_state: + # Save the session state + self.save_state() + + # Emit the torrent_added signal + self.signals.emit("torrent_added", torrent.torrent_id) + + return torrent.torrent_id + + def load_torrent(self, torrent_id): + """Load a torrent file from state and return it's torrent info""" + filedump = None + # Get the torrent data from the torrent file + try: + log.debug("Attempting to open %s for add.", torrent_id) + _file = open( + os.path.join( + self.config["state_location"], torrent_id + ".torrent"), + "rb") + filedump = lt.bdecode(_file.read()) + _file.close() + except (IOError, RuntimeError), e: + log.warning("Unable to open %s: %s", torrent_id, e) + return False + + return filedump + + def remove(self, torrent_id, remove_torrent=False, remove_data=False): + """Remove a torrent from the manager""" + try: + # Remove from libtorrent session + option = 0 + # Remove data if set + if remove_data: + option = 1 + self.session.remove_torrent(self.torrents[torrent_id].handle, + option) + except (RuntimeError, KeyError), e: + log.warning("Error removing torrent: %s", e) + return False + + # Remove the .torrent file if requested + if remove_torrent: + try: + torrent_file = os.path.join( + self.config["torrentfiles_location"], + self.torrents[torrent_id].filename) + os.remove(torrent_file) + except Exception, e: + log.warning("Unable to remove .torrent file: %s", e) + + # Remove the .fastresume if it exists + self.torrents[torrent_id].delete_fastresume() + + # Remove the .torrent file in the state + self.torrents[torrent_id].delete_torrentfile() + + # Remove the torrent from deluge's session + try: + del self.torrents[torrent_id] + except KeyError, ValueError: + return False + + # Save the session state + self.save_state() + return True + + def pause_all(self): + """Pauses all torrents.. Returns a list of torrents paused.""" + torrent_was_paused = False + for key in self.torrents.keys(): + try: + self.torrents[key].pause() + torrent_was_paused = True + except: + log.warning("Unable to pause torrent %s", key) + + return torrent_was_paused + + def resume_all(self): + """Resumes all torrents.. Returns True if at least 1 torrent is resumed""" + torrent_was_resumed = False + for key in self.torrents.keys(): + if self.torrents[key].resume(): + torrent_was_resumed = True + else: + log.warning("Unable to resume torrent %s", key) + + return torrent_was_resumed + + def load_state(self): + """Load the state of the TorrentManager from the torrents.state file""" + state = TorrentManagerState() + + try: + log.debug("Opening torrent state file for load.") + state_file = open( + os.path.join(self.config["state_location"], "torrents.state"), "rb") + state = cPickle.load(state_file) + state_file.close() + except (EOFError, IOError, Exception), e: + log.warning("Unable to load state file: %s", e) + + # Try to use an old state + try: + if dir(state.torrents[0]) != dir(TorrentState()): + for attr in (set(dir(TorrentState())) - set(dir(state.torrents[0]))): + for s in state.torrents: + setattr(s, attr, getattr(TorrentState(), attr, None)) + except Exception, e: + log.warning("Unable to update state file to a compatible version: %s", e) + + # Reorder the state.torrents list to add torrents in the correct queue + # order. + ordered_state = [] + for torrent_state in state.torrents: + for t in ordered_state: + if torrent_state.queue < t.queue: + ordered_state.insert(0, torrent_state) + break + ordered_state.append(torrent_state) + + for torrent_state in ordered_state: + try: + self.add(state=torrent_state, save_state=False) + except AttributeError, e: + log.error("Torrent state file is either corrupt or incompatible!") + break + + # Run the post_session_load plugin hooks + self.plugins.run_post_session_load() + + def save_state(self): + """Save the state of the TorrentManager to the torrents.state file""" + state = TorrentManagerState() + # Create the state for each Torrent and append to the list + for torrent in self.torrents.values(): + paused = False + if torrent.state == "Paused": + paused = True + + torrent_state = TorrentState( + torrent.torrent_id, + torrent.filename, + torrent.get_status(["total_uploaded"])["total_uploaded"], + torrent.trackers, + torrent.compact, + paused, + torrent.save_path, + torrent.max_connections, + torrent.max_upload_slots, + torrent.max_upload_speed, + torrent.max_download_speed, + torrent.prioritize_first_last, + torrent.file_priorities, + torrent.get_queue_position(), + torrent.auto_managed, + torrent.is_finished, + torrent.stop_ratio, + torrent.stop_at_ratio, + torrent.remove_at_ratio + ) + state.torrents.append(torrent_state) + + # Pickle the TorrentManagerState object + try: + log.debug("Saving torrent state file.") + state_file = open( + os.path.join(self.config["state_location"], "torrents.state"), + "wb") + cPickle.dump(state, state_file) + state_file.close() + except IOError: + log.warning("Unable to save state file.") + + # We return True so that the timer thread will continue + return True + + def queue_top(self, torrent_id): + """Queue torrent to top""" + if self.torrents[torrent_id].get_queue_position() == 0: + return False + + self.torrents[torrent_id].handle.queue_position_top() + return True + + def queue_up(self, torrent_id): + """Queue torrent up one position""" + if self.torrents[torrent_id].get_queue_position() == 0: + return False + + self.torrents[torrent_id].handle.queue_position_up() + return True + + def queue_down(self, torrent_id): + """Queue torrent down one position""" + if self.torrents[torrent_id].get_queue_position() == (len(self.torrents) - 1): + return False + + self.torrents[torrent_id].handle.queue_position_down() + return True + + def queue_bottom(self, torrent_id): + """Queue torrent to bottom""" + if self.torrents[torrent_id].get_queue_position() == (len(self.torrents) - 1): + return False + + self.torrents[torrent_id].handle.queue_position_bottom() + return True + + def on_set_max_connections_per_torrent(self, key, value): + """Sets the per-torrent connection limit""" + log.debug("max_connections_per_torrent set to %s..", value) + for key in self.torrents.keys(): + self.torrents[key].set_max_connections(value) + + def on_set_max_upload_slots_per_torrent(self, key, value): + """Sets the per-torrent upload slot limit""" + log.debug("max_upload_slots_per_torrent set to %s..", value) + for key in self.torrents.keys(): + self.torrents[key].set_max_upload_slots(value) + + def on_set_max_upload_speed_per_torrent(self, key, value): + log.debug("max_upload_speed_per_torrent set to %s..", value) + for key in self.torrents.keys(): + self.torrents[key].set_max_upload_speed(value) + + def on_set_max_download_speed_per_torrent(self, key, value): + log.debug("max_download_speed_per_torrent set to %s..", value) + for key in self.torrents.keys(): + self.torrents[key].set_max_download_speed(value) + + ## Alert handlers ## + def on_alert_torrent_finished(self, alert): + log.debug("on_alert_torrent_finished") + # Get the torrent_id + torrent_id = str(alert.handle.info_hash()) + torrent = self.torrents[torrent_id] + log.debug("%s is finished..", torrent_id) + # Move completed download to completed folder if needed + if self.config["move_completed"] and not torrent.is_finished: + if torrent.save_path != self.config["move_completed_path"]: + torrent.move_storage(self.config["move_completed_path"]) + + torrent.is_finished = True + torrent.update_state() + torrent.write_fastresume() + component.get("SignalManager").emit("torrent_finished", torrent_id) + + def on_alert_torrent_paused(self, alert): + log.debug("on_alert_torrent_paused") + # Get the torrent_id + torrent_id = str(alert.handle.info_hash()) + # Set the torrent state + self.torrents[torrent_id].update_state() + component.get("SignalManager").emit("torrent_paused", torrent_id) + + # Write the fastresume file + self.torrents[torrent_id].write_fastresume() + + if torrent_id in self.shutdown_torrent_pause_list: + self.shutdown_torrent_pause_list.remove(torrent_id) + + def on_alert_torrent_checked(self, alert): + log.debug("on_alert_torrent_checked") + # Get the torrent_id + torrent_id = str(alert.handle.info_hash()) + # Set the torrent state + self.torrents[torrent_id].update_state() + + def on_alert_tracker_reply(self, alert): + log.debug("on_alert_tracker_reply") + # Get the torrent_id + torrent_id = str(alert.handle.info_hash()) + # Set the tracker status for the torrent + try: + if alert.message != "Got peers from DHT": + self.torrents[torrent_id].set_tracker_status(_("Announce OK")) + except KeyError: + log.debug("torrent_id doesn't exist.") + + # Check to see if we got any peer information from the tracker + if alert.handle.status().num_complete == -1 or \ + alert.handle.status().num_incomplete == -1: + # We didn't get peer information, so lets send a scrape request + self.torrents[torrent_id].scrape_tracker() + + def on_alert_tracker_announce(self, alert): + log.debug("on_alert_tracker_announce") + # Get the torrent_id + try: + torrent_id = str(alert.handle.info_hash()) + except RuntimeError: + log.debug("Invalid torrent handle.") + return + + # Set the tracker status for the torrent + try: + self.torrents[torrent_id].set_tracker_status(_("Announce Sent")) + except KeyError: + log.debug("torrent_id doesn't exist.") + + def on_alert_tracker(self, alert): + log.debug("on_alert_tracker") + # Get the torrent_id + torrent_id = str(alert.handle.info_hash()) + tracker_status = "%s: %s" % \ + (_("Alert"), str(alert.message()).strip('"')[8:]) + # Set the tracker status for the torrent + try: + self.torrents[torrent_id].set_tracker_status(tracker_status) + except KeyError: + log.debug("torrent_id doesn't exist.") + + def on_alert_tracker_warning(self, alert): + log.debug("on_alert_tracker_warning") + # Get the torrent_id + torrent_id = str(alert.handle.info_hash()) + tracker_status = '%s: %s' % (_("Warning"), str(alert.message())) + # Set the tracker status for the torrent + try: + self.torrents[torrent_id].set_tracker_status(tracker_status) + except KeyError: + log.debug("torrent_id doesn't exist.") + + def on_alert_storage_moved(self, alert): + log.debug("on_alert_storage_moved") + log.debug("save_path: %s", alert.handle.save_path()) + # Get the torrent_id + torrent_id = str(alert.handle.info_hash()) + try: + log.debug("save_path2: %s", self.torrents[torrent_id].handle.save_path()) + self.torrents[torrent_id].set_save_path(alert.handle.save_path()) + except KeyError: + log.debug("torrent_id doesn't exist.") + + def on_alert_torrent_resumed(self, alert): + log.debug("on_alert_torrent_resumed") + torrent = self.torrents[str(alert.handle.info_hash())] + torrent.is_finished = torrent.handle.is_seed() + torrent.update_state() + + def on_alert_state_changed(self, alert): + log.debug("on_alert_state_changed") + torrent_id = str(alert.handle.info_hash()) + self.torrents[torrent_id].update_state() + component.get("SignalManager").emit("torrent_state_changed", torrent_id) + diff --git a/icons/hicolor/128x128/apps/deluge.png b/deluge/data/icons/hicolor/128x128/apps/deluge.png similarity index 99% rename from icons/hicolor/128x128/apps/deluge.png rename to deluge/data/icons/hicolor/128x128/apps/deluge.png index bd3f2b3cf..85e21fafd 100644 Binary files a/icons/hicolor/128x128/apps/deluge.png and b/deluge/data/icons/hicolor/128x128/apps/deluge.png differ diff --git a/icons/hicolor/16x16/apps/deluge.png b/deluge/data/icons/hicolor/16x16/apps/deluge.png similarity index 91% rename from icons/hicolor/16x16/apps/deluge.png rename to deluge/data/icons/hicolor/16x16/apps/deluge.png index 7558aacf9..e39cd0c7e 100644 Binary files a/icons/hicolor/16x16/apps/deluge.png and b/deluge/data/icons/hicolor/16x16/apps/deluge.png differ diff --git a/icons/hicolor/192x192/apps/deluge.png b/deluge/data/icons/hicolor/192x192/apps/deluge.png similarity index 99% rename from icons/hicolor/192x192/apps/deluge.png rename to deluge/data/icons/hicolor/192x192/apps/deluge.png index 06e7105aa..ead465c7d 100644 Binary files a/icons/hicolor/192x192/apps/deluge.png and b/deluge/data/icons/hicolor/192x192/apps/deluge.png differ diff --git a/icons/hicolor/22x22/apps/deluge.png b/deluge/data/icons/hicolor/22x22/apps/deluge.png similarity index 94% rename from icons/hicolor/22x22/apps/deluge.png rename to deluge/data/icons/hicolor/22x22/apps/deluge.png index 51187bdf4..de0fdea7b 100644 Binary files a/icons/hicolor/22x22/apps/deluge.png and b/deluge/data/icons/hicolor/22x22/apps/deluge.png differ diff --git a/icons/hicolor/24x24/apps/deluge.png b/deluge/data/icons/hicolor/24x24/apps/deluge.png similarity index 94% rename from icons/hicolor/24x24/apps/deluge.png rename to deluge/data/icons/hicolor/24x24/apps/deluge.png index 31b14b443..faad5cc25 100644 Binary files a/icons/hicolor/24x24/apps/deluge.png and b/deluge/data/icons/hicolor/24x24/apps/deluge.png differ diff --git a/icons/hicolor/256x256/apps/deluge.png b/deluge/data/icons/hicolor/256x256/apps/deluge.png similarity index 99% rename from icons/hicolor/256x256/apps/deluge.png rename to deluge/data/icons/hicolor/256x256/apps/deluge.png index 04e650d0c..8819b5436 100644 Binary files a/icons/hicolor/256x256/apps/deluge.png and b/deluge/data/icons/hicolor/256x256/apps/deluge.png differ diff --git a/icons/hicolor/32x32/apps/deluge.png b/deluge/data/icons/hicolor/32x32/apps/deluge.png similarity index 96% rename from icons/hicolor/32x32/apps/deluge.png rename to deluge/data/icons/hicolor/32x32/apps/deluge.png index a450a620b..2d272f2ea 100644 Binary files a/icons/hicolor/32x32/apps/deluge.png and b/deluge/data/icons/hicolor/32x32/apps/deluge.png differ diff --git a/icons/hicolor/36x36/apps/deluge.png b/deluge/data/icons/hicolor/36x36/apps/deluge.png similarity index 97% rename from icons/hicolor/36x36/apps/deluge.png rename to deluge/data/icons/hicolor/36x36/apps/deluge.png index 73ec3fb7f..56c9c98a8 100644 Binary files a/icons/hicolor/36x36/apps/deluge.png and b/deluge/data/icons/hicolor/36x36/apps/deluge.png differ diff --git a/icons/hicolor/48x48/apps/deluge.png b/deluge/data/icons/hicolor/48x48/apps/deluge.png similarity index 98% rename from icons/hicolor/48x48/apps/deluge.png rename to deluge/data/icons/hicolor/48x48/apps/deluge.png index b4e1d7aa8..37fcf8e45 100644 Binary files a/icons/hicolor/48x48/apps/deluge.png and b/deluge/data/icons/hicolor/48x48/apps/deluge.png differ diff --git a/icons/hicolor/64x64/apps/deluge.png b/deluge/data/icons/hicolor/64x64/apps/deluge.png similarity index 98% rename from icons/hicolor/64x64/apps/deluge.png rename to deluge/data/icons/hicolor/64x64/apps/deluge.png index 891781201..ca004d0ca 100644 Binary files a/icons/hicolor/64x64/apps/deluge.png and b/deluge/data/icons/hicolor/64x64/apps/deluge.png differ diff --git a/icons/hicolor/72x72/apps/deluge.png b/deluge/data/icons/hicolor/72x72/apps/deluge.png similarity index 98% rename from icons/hicolor/72x72/apps/deluge.png rename to deluge/data/icons/hicolor/72x72/apps/deluge.png index e1672809e..22e2a0185 100644 Binary files a/icons/hicolor/72x72/apps/deluge.png and b/deluge/data/icons/hicolor/72x72/apps/deluge.png differ diff --git a/icons/hicolor/96x96/apps/deluge.png b/deluge/data/icons/hicolor/96x96/apps/deluge.png similarity index 99% rename from icons/hicolor/96x96/apps/deluge.png rename to deluge/data/icons/hicolor/96x96/apps/deluge.png index 19e65d940..6b182a48d 100644 Binary files a/icons/hicolor/96x96/apps/deluge.png and b/deluge/data/icons/hicolor/96x96/apps/deluge.png differ diff --git a/icons/scalable/apps/deluge.svg b/deluge/data/icons/scalable/apps/deluge.svg similarity index 100% rename from icons/scalable/apps/deluge.svg rename to deluge/data/icons/scalable/apps/deluge.svg diff --git a/logo.svg b/deluge/data/pixmaps/alert.svg similarity index 70% rename from logo.svg rename to deluge/data/pixmaps/alert.svg index 69e59776d..864a0e10c 100644 --- a/logo.svg +++ b/deluge/data/pixmaps/alert.svg @@ -14,11 +14,11 @@ id="svg3440" sodipodi:version="0.32" inkscape:version="0.45" - sodipodi:docbase="/home/zach/deluge/trunk" - sodipodi:docname="deluge.svg" - inkscape:export-filename="/home/zach/deluge.png" - inkscape:export-xdpi="480" - inkscape:export-ydpi="480" + sodipodi:docbase="/home/andrew" + sodipodi:docname="alert.svg" + inkscape:export-filename="/home/andrew/alert16.png" + inkscape:export-xdpi="32.603073" + inkscape:export-ydpi="32.603073" inkscape:output_extension="org.inkscape.output.svg.inkscape" sodipodi:modified="TRUE"> - @@ -345,58 +334,27 @@ inkscape:label="Layer 1" inkscape:groupmode="layer"> - - - - - - + ! diff --git a/deluge/data/pixmaps/alert16.png b/deluge/data/pixmaps/alert16.png new file mode 100644 index 000000000..19a27ddb4 Binary files /dev/null and b/deluge/data/pixmaps/alert16.png differ diff --git a/deluge/data/pixmaps/checking.svg b/deluge/data/pixmaps/checking.svg new file mode 100644 index 000000000..14dc4877f --- /dev/null +++ b/deluge/data/pixmaps/checking.svg @@ -0,0 +1,297 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Internet Category + + + Jakub Steiner + + + + + Tuomas Kuosmanen + + + + http://jimmac.musichall.cz + + + internet + tools + applications + category + + + + + + + + + + + + + + + + + + + + diff --git a/deluge/data/pixmaps/checking16.png b/deluge/data/pixmaps/checking16.png new file mode 100644 index 000000000..33ecc9153 Binary files /dev/null and b/deluge/data/pixmaps/checking16.png differ diff --git a/pixmaps/deluge-about.png b/deluge/data/pixmaps/deluge-about.png similarity index 100% rename from pixmaps/deluge-about.png rename to deluge/data/pixmaps/deluge-about.png diff --git a/pixmaps/deluge.png b/deluge/data/pixmaps/deluge.png similarity index 100% rename from pixmaps/deluge.png rename to deluge/data/pixmaps/deluge.png diff --git a/pixmaps/deluge.svg b/deluge/data/pixmaps/deluge.svg similarity index 100% rename from pixmaps/deluge.svg rename to deluge/data/pixmaps/deluge.svg diff --git a/deluge/data/pixmaps/dht16.png b/deluge/data/pixmaps/dht16.png new file mode 100644 index 000000000..be59e5e61 Binary files /dev/null and b/deluge/data/pixmaps/dht16.png differ diff --git a/plugins/FlexRSS/FlexRSS.svg b/deluge/data/pixmaps/downloading.svg similarity index 66% rename from plugins/FlexRSS/FlexRSS.svg rename to deluge/data/pixmaps/downloading.svg index c996707df..ea371e87b 100644 --- a/plugins/FlexRSS/FlexRSS.svg +++ b/deluge/data/pixmaps/downloading.svg @@ -13,12 +13,13 @@ height="48px" id="svg3440" sodipodi:version="0.32" - inkscape:version="0.45" - sodipodi:docname="FlexRSS.svg" - inkscape:export-xdpi="480" - inkscape:export-ydpi="480" - inkscape:output_extension="org.inkscape.output.svg.inkscape" - sodipodi:modified="true"> + inkscape:version="0.45.1" + sodipodi:docbase="/home/andrew/Projects/deluge-icons" + sodipodi:docname="downloading-border.svg" + inkscape:export-filename="/home/andrew/Projects/deluge-icons/downloading16.png" + inkscape:export-xdpi="32.603073" + inkscape:export-ydpi="32.603073" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + id="stop4991" + offset="0.0000000" + style="stop-color:#d3e9ff;stop-opacity:1.0000000;" /> + id="stop4993" + offset="0.15517241" + style="stop-color:#d3e9ff;stop-opacity:1.0000000;" /> + id="stop4995" + offset="0.75000000" + style="stop-color:#4074ae;stop-opacity:1.0000000;" /> - - - + id="stop4997" + offset="1.0000000" + style="stop-color:#36486c;stop-opacity:1.0000000;" /> @@ -238,6 +227,28 @@ fx="12.071323" fy="12.493138" r="6.7175145" /> + + - @@ -333,61 +333,18 @@ inkscape:label="Layer 1" inkscape:groupmode="layer"> - + style="fill:#8dd35f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 23.942923,0.9561338 L 37.330543,18.266721 C 46.998995,29.84687 41.49692,43.923891 26.7742,45.000491 C 6.0597413,45.582655 6.5086231,27.37483 11.255313,18.609381 L 23.942923,0.9561338 z " + id="path2069" + sodipodi:nodetypes="ccccc" /> - - - - + style="fill:#b7e399;fill-opacity:1;stroke:#000000;stroke-opacity:1;marker-end:none;stroke-width:0.7;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-linecap:round;stroke-linejoin:round" + d="M 19.34375 17.5625 C 19.34375 21.552083 19.34375 25.541668 19.34375 29.53125 C 17.636839 29.528128 15.925661 29.534372 14.21875 29.53125 C 17.623975 32.921687 21.032275 36.297063 24.4375 39.6875 C 27.880752 36.309591 31.337996 32.94041 34.78125 29.5625 C 32.928627 29.559111 31.071373 29.565889 29.21875 29.5625 C 29.21875 25.5625 29.21875 21.562501 29.21875 17.5625 C 25.927083 17.5625 22.635418 17.562501 19.34375 17.5625 z " + id="rect2634" /> diff --git a/pixmaps/downloading16.png b/deluge/data/pixmaps/downloading16.png similarity index 100% rename from pixmaps/downloading16.png rename to deluge/data/pixmaps/downloading16.png diff --git a/pixmaps/flags18x12/FLAGS_LICENCE b/deluge/data/pixmaps/flags/FLAGS_LICENCE similarity index 100% rename from pixmaps/flags18x12/FLAGS_LICENCE rename to deluge/data/pixmaps/flags/FLAGS_LICENCE diff --git a/deluge/data/pixmaps/flags/ad.png b/deluge/data/pixmaps/flags/ad.png new file mode 100644 index 000000000..625ca84f9 Binary files /dev/null and b/deluge/data/pixmaps/flags/ad.png differ diff --git a/deluge/data/pixmaps/flags/ae.png b/deluge/data/pixmaps/flags/ae.png new file mode 100644 index 000000000..ef3a1ecfc Binary files /dev/null and b/deluge/data/pixmaps/flags/ae.png differ diff --git a/deluge/data/pixmaps/flags/af.png b/deluge/data/pixmaps/flags/af.png new file mode 100644 index 000000000..a4742e299 Binary files /dev/null and b/deluge/data/pixmaps/flags/af.png differ diff --git a/deluge/data/pixmaps/flags/ag.png b/deluge/data/pixmaps/flags/ag.png new file mode 100644 index 000000000..556d5504d Binary files /dev/null and b/deluge/data/pixmaps/flags/ag.png differ diff --git a/deluge/data/pixmaps/flags/ai.png b/deluge/data/pixmaps/flags/ai.png new file mode 100644 index 000000000..74ed29d92 Binary files /dev/null and b/deluge/data/pixmaps/flags/ai.png differ diff --git a/deluge/data/pixmaps/flags/al.png b/deluge/data/pixmaps/flags/al.png new file mode 100644 index 000000000..92354cb6e Binary files /dev/null and b/deluge/data/pixmaps/flags/al.png differ diff --git a/deluge/data/pixmaps/flags/am.png b/deluge/data/pixmaps/flags/am.png new file mode 100644 index 000000000..344a2a86c Binary files /dev/null and b/deluge/data/pixmaps/flags/am.png differ diff --git a/deluge/data/pixmaps/flags/an.png b/deluge/data/pixmaps/flags/an.png new file mode 100644 index 000000000..633e4b89f Binary files /dev/null and b/deluge/data/pixmaps/flags/an.png differ diff --git a/deluge/data/pixmaps/flags/ao.png b/deluge/data/pixmaps/flags/ao.png new file mode 100644 index 000000000..bcbd1d6d4 Binary files /dev/null and b/deluge/data/pixmaps/flags/ao.png differ diff --git a/pixmaps/flags18x12/aq.png b/deluge/data/pixmaps/flags/aq.png similarity index 100% rename from pixmaps/flags18x12/aq.png rename to deluge/data/pixmaps/flags/aq.png diff --git a/deluge/data/pixmaps/flags/ar.png b/deluge/data/pixmaps/flags/ar.png new file mode 100644 index 000000000..e5ef8f1fc Binary files /dev/null and b/deluge/data/pixmaps/flags/ar.png differ diff --git a/deluge/data/pixmaps/flags/as.png b/deluge/data/pixmaps/flags/as.png new file mode 100644 index 000000000..32f30e4ce Binary files /dev/null and b/deluge/data/pixmaps/flags/as.png differ diff --git a/deluge/data/pixmaps/flags/at.png b/deluge/data/pixmaps/flags/at.png new file mode 100644 index 000000000..0f15f34f2 Binary files /dev/null and b/deluge/data/pixmaps/flags/at.png differ diff --git a/deluge/data/pixmaps/flags/au.png b/deluge/data/pixmaps/flags/au.png new file mode 100644 index 000000000..a01389a74 Binary files /dev/null and b/deluge/data/pixmaps/flags/au.png differ diff --git a/deluge/data/pixmaps/flags/aw.png b/deluge/data/pixmaps/flags/aw.png new file mode 100644 index 000000000..a3579c2d6 Binary files /dev/null and b/deluge/data/pixmaps/flags/aw.png differ diff --git a/deluge/data/pixmaps/flags/ax.png b/deluge/data/pixmaps/flags/ax.png new file mode 100644 index 000000000..1eea80a7b Binary files /dev/null and b/deluge/data/pixmaps/flags/ax.png differ diff --git a/deluge/data/pixmaps/flags/az.png b/deluge/data/pixmaps/flags/az.png new file mode 100644 index 000000000..4ee9fe5ce Binary files /dev/null and b/deluge/data/pixmaps/flags/az.png differ diff --git a/deluge/data/pixmaps/flags/ba.png b/deluge/data/pixmaps/flags/ba.png new file mode 100644 index 000000000..c77499249 Binary files /dev/null and b/deluge/data/pixmaps/flags/ba.png differ diff --git a/deluge/data/pixmaps/flags/bb.png b/deluge/data/pixmaps/flags/bb.png new file mode 100644 index 000000000..0df19c71d Binary files /dev/null and b/deluge/data/pixmaps/flags/bb.png differ diff --git a/deluge/data/pixmaps/flags/bd.png b/deluge/data/pixmaps/flags/bd.png new file mode 100644 index 000000000..076a8bf87 Binary files /dev/null and b/deluge/data/pixmaps/flags/bd.png differ diff --git a/deluge/data/pixmaps/flags/be.png b/deluge/data/pixmaps/flags/be.png new file mode 100644 index 000000000..d86ebc800 Binary files /dev/null and b/deluge/data/pixmaps/flags/be.png differ diff --git a/deluge/data/pixmaps/flags/bf.png b/deluge/data/pixmaps/flags/bf.png new file mode 100644 index 000000000..ab5ce8fe1 Binary files /dev/null and b/deluge/data/pixmaps/flags/bf.png differ diff --git a/deluge/data/pixmaps/flags/bg.png b/deluge/data/pixmaps/flags/bg.png new file mode 100644 index 000000000..0469f0607 Binary files /dev/null and b/deluge/data/pixmaps/flags/bg.png differ diff --git a/deluge/data/pixmaps/flags/bh.png b/deluge/data/pixmaps/flags/bh.png new file mode 100644 index 000000000..ea8ce6876 Binary files /dev/null and b/deluge/data/pixmaps/flags/bh.png differ diff --git a/deluge/data/pixmaps/flags/bi.png b/deluge/data/pixmaps/flags/bi.png new file mode 100644 index 000000000..5cc2e30cf Binary files /dev/null and b/deluge/data/pixmaps/flags/bi.png differ diff --git a/deluge/data/pixmaps/flags/bj.png b/deluge/data/pixmaps/flags/bj.png new file mode 100644 index 000000000..1cc8b458a Binary files /dev/null and b/deluge/data/pixmaps/flags/bj.png differ diff --git a/deluge/data/pixmaps/flags/bm.png b/deluge/data/pixmaps/flags/bm.png new file mode 100644 index 000000000..c0c7aead8 Binary files /dev/null and b/deluge/data/pixmaps/flags/bm.png differ diff --git a/deluge/data/pixmaps/flags/bn.png b/deluge/data/pixmaps/flags/bn.png new file mode 100644 index 000000000..8fb09849e Binary files /dev/null and b/deluge/data/pixmaps/flags/bn.png differ diff --git a/deluge/data/pixmaps/flags/bo.png b/deluge/data/pixmaps/flags/bo.png new file mode 100644 index 000000000..ce7ba522a Binary files /dev/null and b/deluge/data/pixmaps/flags/bo.png differ diff --git a/deluge/data/pixmaps/flags/br.png b/deluge/data/pixmaps/flags/br.png new file mode 100644 index 000000000..9b1a5538b Binary files /dev/null and b/deluge/data/pixmaps/flags/br.png differ diff --git a/deluge/data/pixmaps/flags/bs.png b/deluge/data/pixmaps/flags/bs.png new file mode 100644 index 000000000..639fa6cfa Binary files /dev/null and b/deluge/data/pixmaps/flags/bs.png differ diff --git a/deluge/data/pixmaps/flags/bt.png b/deluge/data/pixmaps/flags/bt.png new file mode 100644 index 000000000..1d512dfff Binary files /dev/null and b/deluge/data/pixmaps/flags/bt.png differ diff --git a/deluge/data/pixmaps/flags/bv.png b/deluge/data/pixmaps/flags/bv.png new file mode 100644 index 000000000..160b6b5b7 Binary files /dev/null and b/deluge/data/pixmaps/flags/bv.png differ diff --git a/deluge/data/pixmaps/flags/bw.png b/deluge/data/pixmaps/flags/bw.png new file mode 100644 index 000000000..fcb103941 Binary files /dev/null and b/deluge/data/pixmaps/flags/bw.png differ diff --git a/deluge/data/pixmaps/flags/by.png b/deluge/data/pixmaps/flags/by.png new file mode 100644 index 000000000..504774ec1 Binary files /dev/null and b/deluge/data/pixmaps/flags/by.png differ diff --git a/deluge/data/pixmaps/flags/bz.png b/deluge/data/pixmaps/flags/bz.png new file mode 100644 index 000000000..be63ee1c6 Binary files /dev/null and b/deluge/data/pixmaps/flags/bz.png differ diff --git a/deluge/data/pixmaps/flags/ca.png b/deluge/data/pixmaps/flags/ca.png new file mode 100644 index 000000000..1f204193a Binary files /dev/null and b/deluge/data/pixmaps/flags/ca.png differ diff --git a/deluge/data/pixmaps/flags/cc.png b/deluge/data/pixmaps/flags/cc.png new file mode 100644 index 000000000..aed3d3b4e Binary files /dev/null and b/deluge/data/pixmaps/flags/cc.png differ diff --git a/deluge/data/pixmaps/flags/cd.png b/deluge/data/pixmaps/flags/cd.png new file mode 100644 index 000000000..5e4894248 Binary files /dev/null and b/deluge/data/pixmaps/flags/cd.png differ diff --git a/deluge/data/pixmaps/flags/cf.png b/deluge/data/pixmaps/flags/cf.png new file mode 100644 index 000000000..da687bdce Binary files /dev/null and b/deluge/data/pixmaps/flags/cf.png differ diff --git a/deluge/data/pixmaps/flags/cg.png b/deluge/data/pixmaps/flags/cg.png new file mode 100644 index 000000000..a859792ef Binary files /dev/null and b/deluge/data/pixmaps/flags/cg.png differ diff --git a/deluge/data/pixmaps/flags/ch.png b/deluge/data/pixmaps/flags/ch.png new file mode 100644 index 000000000..242ec01aa Binary files /dev/null and b/deluge/data/pixmaps/flags/ch.png differ diff --git a/deluge/data/pixmaps/flags/ci.png b/deluge/data/pixmaps/flags/ci.png new file mode 100644 index 000000000..3f2c62eb4 Binary files /dev/null and b/deluge/data/pixmaps/flags/ci.png differ diff --git a/deluge/data/pixmaps/flags/ck.png b/deluge/data/pixmaps/flags/ck.png new file mode 100644 index 000000000..746d3d6f7 Binary files /dev/null and b/deluge/data/pixmaps/flags/ck.png differ diff --git a/deluge/data/pixmaps/flags/cl.png b/deluge/data/pixmaps/flags/cl.png new file mode 100644 index 000000000..29c6d61bd Binary files /dev/null and b/deluge/data/pixmaps/flags/cl.png differ diff --git a/deluge/data/pixmaps/flags/cm.png b/deluge/data/pixmaps/flags/cm.png new file mode 100644 index 000000000..f65c5bd5a Binary files /dev/null and b/deluge/data/pixmaps/flags/cm.png differ diff --git a/deluge/data/pixmaps/flags/cn.png b/deluge/data/pixmaps/flags/cn.png new file mode 100644 index 000000000..891441462 Binary files /dev/null and b/deluge/data/pixmaps/flags/cn.png differ diff --git a/deluge/data/pixmaps/flags/co.png b/deluge/data/pixmaps/flags/co.png new file mode 100644 index 000000000..a118ff4a1 Binary files /dev/null and b/deluge/data/pixmaps/flags/co.png differ diff --git a/deluge/data/pixmaps/flags/cr.png b/deluge/data/pixmaps/flags/cr.png new file mode 100644 index 000000000..c7a373179 Binary files /dev/null and b/deluge/data/pixmaps/flags/cr.png differ diff --git a/deluge/data/pixmaps/flags/cs.png b/deluge/data/pixmaps/flags/cs.png new file mode 100644 index 000000000..8254790ca Binary files /dev/null and b/deluge/data/pixmaps/flags/cs.png differ diff --git a/deluge/data/pixmaps/flags/cu.png b/deluge/data/pixmaps/flags/cu.png new file mode 100644 index 000000000..083f1d611 Binary files /dev/null and b/deluge/data/pixmaps/flags/cu.png differ diff --git a/deluge/data/pixmaps/flags/cv.png b/deluge/data/pixmaps/flags/cv.png new file mode 100644 index 000000000..a63f7eaf6 Binary files /dev/null and b/deluge/data/pixmaps/flags/cv.png differ diff --git a/deluge/data/pixmaps/flags/cx.png b/deluge/data/pixmaps/flags/cx.png new file mode 100644 index 000000000..48e31adbf Binary files /dev/null and b/deluge/data/pixmaps/flags/cx.png differ diff --git a/deluge/data/pixmaps/flags/cy.png b/deluge/data/pixmaps/flags/cy.png new file mode 100644 index 000000000..5b1ad6c07 Binary files /dev/null and b/deluge/data/pixmaps/flags/cy.png differ diff --git a/deluge/data/pixmaps/flags/cz.png b/deluge/data/pixmaps/flags/cz.png new file mode 100644 index 000000000..c8403dd21 Binary files /dev/null and b/deluge/data/pixmaps/flags/cz.png differ diff --git a/deluge/data/pixmaps/flags/de.png b/deluge/data/pixmaps/flags/de.png new file mode 100644 index 000000000..ac4a97736 Binary files /dev/null and b/deluge/data/pixmaps/flags/de.png differ diff --git a/deluge/data/pixmaps/flags/dj.png b/deluge/data/pixmaps/flags/dj.png new file mode 100644 index 000000000..582af364f Binary files /dev/null and b/deluge/data/pixmaps/flags/dj.png differ diff --git a/deluge/data/pixmaps/flags/dk.png b/deluge/data/pixmaps/flags/dk.png new file mode 100644 index 000000000..e2993d3c5 Binary files /dev/null and b/deluge/data/pixmaps/flags/dk.png differ diff --git a/deluge/data/pixmaps/flags/dm.png b/deluge/data/pixmaps/flags/dm.png new file mode 100644 index 000000000..5fbffcba3 Binary files /dev/null and b/deluge/data/pixmaps/flags/dm.png differ diff --git a/deluge/data/pixmaps/flags/do.png b/deluge/data/pixmaps/flags/do.png new file mode 100644 index 000000000..5a04932d8 Binary files /dev/null and b/deluge/data/pixmaps/flags/do.png differ diff --git a/deluge/data/pixmaps/flags/dz.png b/deluge/data/pixmaps/flags/dz.png new file mode 100644 index 000000000..335c2391d Binary files /dev/null and b/deluge/data/pixmaps/flags/dz.png differ diff --git a/deluge/data/pixmaps/flags/ec.png b/deluge/data/pixmaps/flags/ec.png new file mode 100644 index 000000000..0caa0b1e7 Binary files /dev/null and b/deluge/data/pixmaps/flags/ec.png differ diff --git a/deluge/data/pixmaps/flags/ee.png b/deluge/data/pixmaps/flags/ee.png new file mode 100644 index 000000000..0c82efb7d Binary files /dev/null and b/deluge/data/pixmaps/flags/ee.png differ diff --git a/deluge/data/pixmaps/flags/eg.png b/deluge/data/pixmaps/flags/eg.png new file mode 100644 index 000000000..8a3f7a10b Binary files /dev/null and b/deluge/data/pixmaps/flags/eg.png differ diff --git a/deluge/data/pixmaps/flags/eh.png b/deluge/data/pixmaps/flags/eh.png new file mode 100644 index 000000000..90a1195b4 Binary files /dev/null and b/deluge/data/pixmaps/flags/eh.png differ diff --git a/deluge/data/pixmaps/flags/er.png b/deluge/data/pixmaps/flags/er.png new file mode 100644 index 000000000..13065ae99 Binary files /dev/null and b/deluge/data/pixmaps/flags/er.png differ diff --git a/deluge/data/pixmaps/flags/es.png b/deluge/data/pixmaps/flags/es.png new file mode 100644 index 000000000..c2de2d711 Binary files /dev/null and b/deluge/data/pixmaps/flags/es.png differ diff --git a/deluge/data/pixmaps/flags/et.png b/deluge/data/pixmaps/flags/et.png new file mode 100644 index 000000000..2e893fa05 Binary files /dev/null and b/deluge/data/pixmaps/flags/et.png differ diff --git a/deluge/data/pixmaps/flags/fi.png b/deluge/data/pixmaps/flags/fi.png new file mode 100644 index 000000000..14ec091b8 Binary files /dev/null and b/deluge/data/pixmaps/flags/fi.png differ diff --git a/deluge/data/pixmaps/flags/fj.png b/deluge/data/pixmaps/flags/fj.png new file mode 100644 index 000000000..cee998892 Binary files /dev/null and b/deluge/data/pixmaps/flags/fj.png differ diff --git a/deluge/data/pixmaps/flags/fk.png b/deluge/data/pixmaps/flags/fk.png new file mode 100644 index 000000000..ceaeb27de Binary files /dev/null and b/deluge/data/pixmaps/flags/fk.png differ diff --git a/deluge/data/pixmaps/flags/fm.png b/deluge/data/pixmaps/flags/fm.png new file mode 100644 index 000000000..066bb2473 Binary files /dev/null and b/deluge/data/pixmaps/flags/fm.png differ diff --git a/deluge/data/pixmaps/flags/fo.png b/deluge/data/pixmaps/flags/fo.png new file mode 100644 index 000000000..cbceb809e Binary files /dev/null and b/deluge/data/pixmaps/flags/fo.png differ diff --git a/deluge/data/pixmaps/flags/fr.png b/deluge/data/pixmaps/flags/fr.png new file mode 100644 index 000000000..8332c4ec2 Binary files /dev/null and b/deluge/data/pixmaps/flags/fr.png differ diff --git a/pixmaps/flags18x12/fx.png b/deluge/data/pixmaps/flags/fx.png similarity index 100% rename from pixmaps/flags18x12/fx.png rename to deluge/data/pixmaps/flags/fx.png diff --git a/deluge/data/pixmaps/flags/ga.png b/deluge/data/pixmaps/flags/ga.png new file mode 100644 index 000000000..0e0d43436 Binary files /dev/null and b/deluge/data/pixmaps/flags/ga.png differ diff --git a/deluge/data/pixmaps/flags/gb.png b/deluge/data/pixmaps/flags/gb.png new file mode 100644 index 000000000..ff701e19f Binary files /dev/null and b/deluge/data/pixmaps/flags/gb.png differ diff --git a/deluge/data/pixmaps/flags/gd.png b/deluge/data/pixmaps/flags/gd.png new file mode 100644 index 000000000..9ab57f548 Binary files /dev/null and b/deluge/data/pixmaps/flags/gd.png differ diff --git a/deluge/data/pixmaps/flags/ge.png b/deluge/data/pixmaps/flags/ge.png new file mode 100644 index 000000000..728d97078 Binary files /dev/null and b/deluge/data/pixmaps/flags/ge.png differ diff --git a/deluge/data/pixmaps/flags/gf.png b/deluge/data/pixmaps/flags/gf.png new file mode 100644 index 000000000..8332c4ec2 Binary files /dev/null and b/deluge/data/pixmaps/flags/gf.png differ diff --git a/pixmaps/flags18x12/gg.png b/deluge/data/pixmaps/flags/gg.png similarity index 100% rename from pixmaps/flags18x12/gg.png rename to deluge/data/pixmaps/flags/gg.png diff --git a/deluge/data/pixmaps/flags/gh.png b/deluge/data/pixmaps/flags/gh.png new file mode 100644 index 000000000..4e2f89659 Binary files /dev/null and b/deluge/data/pixmaps/flags/gh.png differ diff --git a/deluge/data/pixmaps/flags/gi.png b/deluge/data/pixmaps/flags/gi.png new file mode 100644 index 000000000..e76797f62 Binary files /dev/null and b/deluge/data/pixmaps/flags/gi.png differ diff --git a/deluge/data/pixmaps/flags/gl.png b/deluge/data/pixmaps/flags/gl.png new file mode 100644 index 000000000..ef12a73bf Binary files /dev/null and b/deluge/data/pixmaps/flags/gl.png differ diff --git a/deluge/data/pixmaps/flags/gm.png b/deluge/data/pixmaps/flags/gm.png new file mode 100644 index 000000000..0720b667a Binary files /dev/null and b/deluge/data/pixmaps/flags/gm.png differ diff --git a/deluge/data/pixmaps/flags/gn.png b/deluge/data/pixmaps/flags/gn.png new file mode 100644 index 000000000..ea660b01f Binary files /dev/null and b/deluge/data/pixmaps/flags/gn.png differ diff --git a/deluge/data/pixmaps/flags/gp.png b/deluge/data/pixmaps/flags/gp.png new file mode 100644 index 000000000..dbb086d00 Binary files /dev/null and b/deluge/data/pixmaps/flags/gp.png differ diff --git a/deluge/data/pixmaps/flags/gq.png b/deluge/data/pixmaps/flags/gq.png new file mode 100644 index 000000000..ebe20a28d Binary files /dev/null and b/deluge/data/pixmaps/flags/gq.png differ diff --git a/deluge/data/pixmaps/flags/gr.png b/deluge/data/pixmaps/flags/gr.png new file mode 100644 index 000000000..8651ade7c Binary files /dev/null and b/deluge/data/pixmaps/flags/gr.png differ diff --git a/deluge/data/pixmaps/flags/gs.png b/deluge/data/pixmaps/flags/gs.png new file mode 100644 index 000000000..7ef0bf598 Binary files /dev/null and b/deluge/data/pixmaps/flags/gs.png differ diff --git a/deluge/data/pixmaps/flags/gt.png b/deluge/data/pixmaps/flags/gt.png new file mode 100644 index 000000000..c43a70d36 Binary files /dev/null and b/deluge/data/pixmaps/flags/gt.png differ diff --git a/deluge/data/pixmaps/flags/gu.png b/deluge/data/pixmaps/flags/gu.png new file mode 100644 index 000000000..92f37c053 Binary files /dev/null and b/deluge/data/pixmaps/flags/gu.png differ diff --git a/deluge/data/pixmaps/flags/gw.png b/deluge/data/pixmaps/flags/gw.png new file mode 100644 index 000000000..b37bcf06b Binary files /dev/null and b/deluge/data/pixmaps/flags/gw.png differ diff --git a/deluge/data/pixmaps/flags/gy.png b/deluge/data/pixmaps/flags/gy.png new file mode 100644 index 000000000..22cbe2f59 Binary files /dev/null and b/deluge/data/pixmaps/flags/gy.png differ diff --git a/deluge/data/pixmaps/flags/hk.png b/deluge/data/pixmaps/flags/hk.png new file mode 100644 index 000000000..d5c380ca9 Binary files /dev/null and b/deluge/data/pixmaps/flags/hk.png differ diff --git a/deluge/data/pixmaps/flags/hm.png b/deluge/data/pixmaps/flags/hm.png new file mode 100644 index 000000000..a01389a74 Binary files /dev/null and b/deluge/data/pixmaps/flags/hm.png differ diff --git a/deluge/data/pixmaps/flags/hn.png b/deluge/data/pixmaps/flags/hn.png new file mode 100644 index 000000000..96f838859 Binary files /dev/null and b/deluge/data/pixmaps/flags/hn.png differ diff --git a/deluge/data/pixmaps/flags/hr.png b/deluge/data/pixmaps/flags/hr.png new file mode 100644 index 000000000..696b51546 Binary files /dev/null and b/deluge/data/pixmaps/flags/hr.png differ diff --git a/deluge/data/pixmaps/flags/ht.png b/deluge/data/pixmaps/flags/ht.png new file mode 100644 index 000000000..416052af7 Binary files /dev/null and b/deluge/data/pixmaps/flags/ht.png differ diff --git a/deluge/data/pixmaps/flags/hu.png b/deluge/data/pixmaps/flags/hu.png new file mode 100644 index 000000000..7baafe44d Binary files /dev/null and b/deluge/data/pixmaps/flags/hu.png differ diff --git a/deluge/data/pixmaps/flags/id.png b/deluge/data/pixmaps/flags/id.png new file mode 100644 index 000000000..c6bc0fafa Binary files /dev/null and b/deluge/data/pixmaps/flags/id.png differ diff --git a/deluge/data/pixmaps/flags/ie.png b/deluge/data/pixmaps/flags/ie.png new file mode 100644 index 000000000..26baa31e1 Binary files /dev/null and b/deluge/data/pixmaps/flags/ie.png differ diff --git a/deluge/data/pixmaps/flags/il.png b/deluge/data/pixmaps/flags/il.png new file mode 100644 index 000000000..2ca772d0b Binary files /dev/null and b/deluge/data/pixmaps/flags/il.png differ diff --git a/deluge/data/pixmaps/flags/in.png b/deluge/data/pixmaps/flags/in.png new file mode 100644 index 000000000..e4d7e81a9 Binary files /dev/null and b/deluge/data/pixmaps/flags/in.png differ diff --git a/deluge/data/pixmaps/flags/io.png b/deluge/data/pixmaps/flags/io.png new file mode 100644 index 000000000..3e74b6a31 Binary files /dev/null and b/deluge/data/pixmaps/flags/io.png differ diff --git a/deluge/data/pixmaps/flags/iq.png b/deluge/data/pixmaps/flags/iq.png new file mode 100644 index 000000000..878a35140 Binary files /dev/null and b/deluge/data/pixmaps/flags/iq.png differ diff --git a/deluge/data/pixmaps/flags/ir.png b/deluge/data/pixmaps/flags/ir.png new file mode 100644 index 000000000..c5fd136ae Binary files /dev/null and b/deluge/data/pixmaps/flags/ir.png differ diff --git a/deluge/data/pixmaps/flags/is.png b/deluge/data/pixmaps/flags/is.png new file mode 100644 index 000000000..b8f6d0f06 Binary files /dev/null and b/deluge/data/pixmaps/flags/is.png differ diff --git a/deluge/data/pixmaps/flags/it.png b/deluge/data/pixmaps/flags/it.png new file mode 100644 index 000000000..89692f74f Binary files /dev/null and b/deluge/data/pixmaps/flags/it.png differ diff --git a/pixmaps/flags18x12/je.png b/deluge/data/pixmaps/flags/je.png similarity index 100% rename from pixmaps/flags18x12/je.png rename to deluge/data/pixmaps/flags/je.png diff --git a/deluge/data/pixmaps/flags/jm.png b/deluge/data/pixmaps/flags/jm.png new file mode 100644 index 000000000..7be119e03 Binary files /dev/null and b/deluge/data/pixmaps/flags/jm.png differ diff --git a/deluge/data/pixmaps/flags/jo.png b/deluge/data/pixmaps/flags/jo.png new file mode 100644 index 000000000..11bd4972b Binary files /dev/null and b/deluge/data/pixmaps/flags/jo.png differ diff --git a/deluge/data/pixmaps/flags/jp.png b/deluge/data/pixmaps/flags/jp.png new file mode 100644 index 000000000..325fbad3f Binary files /dev/null and b/deluge/data/pixmaps/flags/jp.png differ diff --git a/deluge/data/pixmaps/flags/ke.png b/deluge/data/pixmaps/flags/ke.png new file mode 100644 index 000000000..51879adf1 Binary files /dev/null and b/deluge/data/pixmaps/flags/ke.png differ diff --git a/deluge/data/pixmaps/flags/kg.png b/deluge/data/pixmaps/flags/kg.png new file mode 100644 index 000000000..0a818f67e Binary files /dev/null and b/deluge/data/pixmaps/flags/kg.png differ diff --git a/deluge/data/pixmaps/flags/kh.png b/deluge/data/pixmaps/flags/kh.png new file mode 100644 index 000000000..30f6bb1b9 Binary files /dev/null and b/deluge/data/pixmaps/flags/kh.png differ diff --git a/deluge/data/pixmaps/flags/ki.png b/deluge/data/pixmaps/flags/ki.png new file mode 100644 index 000000000..2dcce4b33 Binary files /dev/null and b/deluge/data/pixmaps/flags/ki.png differ diff --git a/deluge/data/pixmaps/flags/km.png b/deluge/data/pixmaps/flags/km.png new file mode 100644 index 000000000..812b2f56c Binary files /dev/null and b/deluge/data/pixmaps/flags/km.png differ diff --git a/deluge/data/pixmaps/flags/kn.png b/deluge/data/pixmaps/flags/kn.png new file mode 100644 index 000000000..febd5b486 Binary files /dev/null and b/deluge/data/pixmaps/flags/kn.png differ diff --git a/deluge/data/pixmaps/flags/kp.png b/deluge/data/pixmaps/flags/kp.png new file mode 100644 index 000000000..d3d509aa8 Binary files /dev/null and b/deluge/data/pixmaps/flags/kp.png differ diff --git a/deluge/data/pixmaps/flags/kr.png b/deluge/data/pixmaps/flags/kr.png new file mode 100644 index 000000000..9c0a78eb9 Binary files /dev/null and b/deluge/data/pixmaps/flags/kr.png differ diff --git a/deluge/data/pixmaps/flags/kw.png b/deluge/data/pixmaps/flags/kw.png new file mode 100644 index 000000000..96546da32 Binary files /dev/null and b/deluge/data/pixmaps/flags/kw.png differ diff --git a/deluge/data/pixmaps/flags/ky.png b/deluge/data/pixmaps/flags/ky.png new file mode 100644 index 000000000..15c5f8e47 Binary files /dev/null and b/deluge/data/pixmaps/flags/ky.png differ diff --git a/deluge/data/pixmaps/flags/kz.png b/deluge/data/pixmaps/flags/kz.png new file mode 100644 index 000000000..45a8c8874 Binary files /dev/null and b/deluge/data/pixmaps/flags/kz.png differ diff --git a/deluge/data/pixmaps/flags/la.png b/deluge/data/pixmaps/flags/la.png new file mode 100644 index 000000000..e28acd018 Binary files /dev/null and b/deluge/data/pixmaps/flags/la.png differ diff --git a/deluge/data/pixmaps/flags/lb.png b/deluge/data/pixmaps/flags/lb.png new file mode 100644 index 000000000..d0d452bf8 Binary files /dev/null and b/deluge/data/pixmaps/flags/lb.png differ diff --git a/deluge/data/pixmaps/flags/lc.png b/deluge/data/pixmaps/flags/lc.png new file mode 100644 index 000000000..a47d06554 Binary files /dev/null and b/deluge/data/pixmaps/flags/lc.png differ diff --git a/deluge/data/pixmaps/flags/li.png b/deluge/data/pixmaps/flags/li.png new file mode 100644 index 000000000..6469909c0 Binary files /dev/null and b/deluge/data/pixmaps/flags/li.png differ diff --git a/deluge/data/pixmaps/flags/lk.png b/deluge/data/pixmaps/flags/lk.png new file mode 100644 index 000000000..088aad6db Binary files /dev/null and b/deluge/data/pixmaps/flags/lk.png differ diff --git a/deluge/data/pixmaps/flags/lr.png b/deluge/data/pixmaps/flags/lr.png new file mode 100644 index 000000000..89a5bc7e7 Binary files /dev/null and b/deluge/data/pixmaps/flags/lr.png differ diff --git a/deluge/data/pixmaps/flags/ls.png b/deluge/data/pixmaps/flags/ls.png new file mode 100644 index 000000000..33fdef101 Binary files /dev/null and b/deluge/data/pixmaps/flags/ls.png differ diff --git a/deluge/data/pixmaps/flags/lt.png b/deluge/data/pixmaps/flags/lt.png new file mode 100644 index 000000000..c8ef0da09 Binary files /dev/null and b/deluge/data/pixmaps/flags/lt.png differ diff --git a/deluge/data/pixmaps/flags/lu.png b/deluge/data/pixmaps/flags/lu.png new file mode 100644 index 000000000..4cabba98a Binary files /dev/null and b/deluge/data/pixmaps/flags/lu.png differ diff --git a/deluge/data/pixmaps/flags/lv.png b/deluge/data/pixmaps/flags/lv.png new file mode 100644 index 000000000..49b699810 Binary files /dev/null and b/deluge/data/pixmaps/flags/lv.png differ diff --git a/deluge/data/pixmaps/flags/ly.png b/deluge/data/pixmaps/flags/ly.png new file mode 100644 index 000000000..b163a9f8a Binary files /dev/null and b/deluge/data/pixmaps/flags/ly.png differ diff --git a/deluge/data/pixmaps/flags/ma.png b/deluge/data/pixmaps/flags/ma.png new file mode 100644 index 000000000..f38677028 Binary files /dev/null and b/deluge/data/pixmaps/flags/ma.png differ diff --git a/deluge/data/pixmaps/flags/mc.png b/deluge/data/pixmaps/flags/mc.png new file mode 100644 index 000000000..1aa830f12 Binary files /dev/null and b/deluge/data/pixmaps/flags/mc.png differ diff --git a/deluge/data/pixmaps/flags/md.png b/deluge/data/pixmaps/flags/md.png new file mode 100644 index 000000000..4e92c1890 Binary files /dev/null and b/deluge/data/pixmaps/flags/md.png differ diff --git a/deluge/data/pixmaps/flags/me.png b/deluge/data/pixmaps/flags/me.png new file mode 100644 index 000000000..ac7253558 Binary files /dev/null and b/deluge/data/pixmaps/flags/me.png differ diff --git a/deluge/data/pixmaps/flags/mg.png b/deluge/data/pixmaps/flags/mg.png new file mode 100644 index 000000000..d2715b3d0 Binary files /dev/null and b/deluge/data/pixmaps/flags/mg.png differ diff --git a/deluge/data/pixmaps/flags/mh.png b/deluge/data/pixmaps/flags/mh.png new file mode 100644 index 000000000..fb523a8c3 Binary files /dev/null and b/deluge/data/pixmaps/flags/mh.png differ diff --git a/deluge/data/pixmaps/flags/mk.png b/deluge/data/pixmaps/flags/mk.png new file mode 100644 index 000000000..db173aaff Binary files /dev/null and b/deluge/data/pixmaps/flags/mk.png differ diff --git a/deluge/data/pixmaps/flags/ml.png b/deluge/data/pixmaps/flags/ml.png new file mode 100644 index 000000000..2cec8ba44 Binary files /dev/null and b/deluge/data/pixmaps/flags/ml.png differ diff --git a/deluge/data/pixmaps/flags/mm.png b/deluge/data/pixmaps/flags/mm.png new file mode 100644 index 000000000..f464f67ff Binary files /dev/null and b/deluge/data/pixmaps/flags/mm.png differ diff --git a/deluge/data/pixmaps/flags/mn.png b/deluge/data/pixmaps/flags/mn.png new file mode 100644 index 000000000..9396355db Binary files /dev/null and b/deluge/data/pixmaps/flags/mn.png differ diff --git a/deluge/data/pixmaps/flags/mo.png b/deluge/data/pixmaps/flags/mo.png new file mode 100644 index 000000000..deb801dda Binary files /dev/null and b/deluge/data/pixmaps/flags/mo.png differ diff --git a/deluge/data/pixmaps/flags/mp.png b/deluge/data/pixmaps/flags/mp.png new file mode 100644 index 000000000..298d588b1 Binary files /dev/null and b/deluge/data/pixmaps/flags/mp.png differ diff --git a/deluge/data/pixmaps/flags/mq.png b/deluge/data/pixmaps/flags/mq.png new file mode 100644 index 000000000..010143b38 Binary files /dev/null and b/deluge/data/pixmaps/flags/mq.png differ diff --git a/deluge/data/pixmaps/flags/mr.png b/deluge/data/pixmaps/flags/mr.png new file mode 100644 index 000000000..319546b10 Binary files /dev/null and b/deluge/data/pixmaps/flags/mr.png differ diff --git a/deluge/data/pixmaps/flags/ms.png b/deluge/data/pixmaps/flags/ms.png new file mode 100644 index 000000000..d4cbb433d Binary files /dev/null and b/deluge/data/pixmaps/flags/ms.png differ diff --git a/deluge/data/pixmaps/flags/mt.png b/deluge/data/pixmaps/flags/mt.png new file mode 100644 index 000000000..00af94871 Binary files /dev/null and b/deluge/data/pixmaps/flags/mt.png differ diff --git a/deluge/data/pixmaps/flags/mu.png b/deluge/data/pixmaps/flags/mu.png new file mode 100644 index 000000000..b7fdce1bd Binary files /dev/null and b/deluge/data/pixmaps/flags/mu.png differ diff --git a/deluge/data/pixmaps/flags/mv.png b/deluge/data/pixmaps/flags/mv.png new file mode 100644 index 000000000..5073d9ec4 Binary files /dev/null and b/deluge/data/pixmaps/flags/mv.png differ diff --git a/deluge/data/pixmaps/flags/mw.png b/deluge/data/pixmaps/flags/mw.png new file mode 100644 index 000000000..13886e9f8 Binary files /dev/null and b/deluge/data/pixmaps/flags/mw.png differ diff --git a/deluge/data/pixmaps/flags/mx.png b/deluge/data/pixmaps/flags/mx.png new file mode 100644 index 000000000..5bc58ab3e Binary files /dev/null and b/deluge/data/pixmaps/flags/mx.png differ diff --git a/deluge/data/pixmaps/flags/my.png b/deluge/data/pixmaps/flags/my.png new file mode 100644 index 000000000..9034cbab2 Binary files /dev/null and b/deluge/data/pixmaps/flags/my.png differ diff --git a/deluge/data/pixmaps/flags/mz.png b/deluge/data/pixmaps/flags/mz.png new file mode 100644 index 000000000..76405e063 Binary files /dev/null and b/deluge/data/pixmaps/flags/mz.png differ diff --git a/deluge/data/pixmaps/flags/na.png b/deluge/data/pixmaps/flags/na.png new file mode 100644 index 000000000..63358c67d Binary files /dev/null and b/deluge/data/pixmaps/flags/na.png differ diff --git a/deluge/data/pixmaps/flags/nc.png b/deluge/data/pixmaps/flags/nc.png new file mode 100644 index 000000000..2cad28378 Binary files /dev/null and b/deluge/data/pixmaps/flags/nc.png differ diff --git a/deluge/data/pixmaps/flags/ne.png b/deluge/data/pixmaps/flags/ne.png new file mode 100644 index 000000000..d85f424f3 Binary files /dev/null and b/deluge/data/pixmaps/flags/ne.png differ diff --git a/deluge/data/pixmaps/flags/nf.png b/deluge/data/pixmaps/flags/nf.png new file mode 100644 index 000000000..f9bcdda12 Binary files /dev/null and b/deluge/data/pixmaps/flags/nf.png differ diff --git a/deluge/data/pixmaps/flags/ng.png b/deluge/data/pixmaps/flags/ng.png new file mode 100644 index 000000000..3eea2e020 Binary files /dev/null and b/deluge/data/pixmaps/flags/ng.png differ diff --git a/deluge/data/pixmaps/flags/ni.png b/deluge/data/pixmaps/flags/ni.png new file mode 100644 index 000000000..3969aaaae Binary files /dev/null and b/deluge/data/pixmaps/flags/ni.png differ diff --git a/deluge/data/pixmaps/flags/nl.png b/deluge/data/pixmaps/flags/nl.png new file mode 100644 index 000000000..fe44791e3 Binary files /dev/null and b/deluge/data/pixmaps/flags/nl.png differ diff --git a/deluge/data/pixmaps/flags/no.png b/deluge/data/pixmaps/flags/no.png new file mode 100644 index 000000000..160b6b5b7 Binary files /dev/null and b/deluge/data/pixmaps/flags/no.png differ diff --git a/deluge/data/pixmaps/flags/np.png b/deluge/data/pixmaps/flags/np.png new file mode 100644 index 000000000..aeb058b7e Binary files /dev/null and b/deluge/data/pixmaps/flags/np.png differ diff --git a/deluge/data/pixmaps/flags/nr.png b/deluge/data/pixmaps/flags/nr.png new file mode 100644 index 000000000..705fc337c Binary files /dev/null and b/deluge/data/pixmaps/flags/nr.png differ diff --git a/deluge/data/pixmaps/flags/nu.png b/deluge/data/pixmaps/flags/nu.png new file mode 100644 index 000000000..c3ce4aedd Binary files /dev/null and b/deluge/data/pixmaps/flags/nu.png differ diff --git a/deluge/data/pixmaps/flags/nz.png b/deluge/data/pixmaps/flags/nz.png new file mode 100644 index 000000000..10d6306d1 Binary files /dev/null and b/deluge/data/pixmaps/flags/nz.png differ diff --git a/deluge/data/pixmaps/flags/om.png b/deluge/data/pixmaps/flags/om.png new file mode 100644 index 000000000..2ffba7e8c Binary files /dev/null and b/deluge/data/pixmaps/flags/om.png differ diff --git a/deluge/data/pixmaps/flags/pa.png b/deluge/data/pixmaps/flags/pa.png new file mode 100644 index 000000000..9b2ee9a78 Binary files /dev/null and b/deluge/data/pixmaps/flags/pa.png differ diff --git a/deluge/data/pixmaps/flags/pe.png b/deluge/data/pixmaps/flags/pe.png new file mode 100644 index 000000000..62a04977f Binary files /dev/null and b/deluge/data/pixmaps/flags/pe.png differ diff --git a/deluge/data/pixmaps/flags/pf.png b/deluge/data/pixmaps/flags/pf.png new file mode 100644 index 000000000..771a0f652 Binary files /dev/null and b/deluge/data/pixmaps/flags/pf.png differ diff --git a/deluge/data/pixmaps/flags/pg.png b/deluge/data/pixmaps/flags/pg.png new file mode 100644 index 000000000..10d623349 Binary files /dev/null and b/deluge/data/pixmaps/flags/pg.png differ diff --git a/deluge/data/pixmaps/flags/ph.png b/deluge/data/pixmaps/flags/ph.png new file mode 100644 index 000000000..b89e15935 Binary files /dev/null and b/deluge/data/pixmaps/flags/ph.png differ diff --git a/deluge/data/pixmaps/flags/pk.png b/deluge/data/pixmaps/flags/pk.png new file mode 100644 index 000000000..e9df70ca4 Binary files /dev/null and b/deluge/data/pixmaps/flags/pk.png differ diff --git a/deluge/data/pixmaps/flags/pl.png b/deluge/data/pixmaps/flags/pl.png new file mode 100644 index 000000000..d413d010b Binary files /dev/null and b/deluge/data/pixmaps/flags/pl.png differ diff --git a/deluge/data/pixmaps/flags/pm.png b/deluge/data/pixmaps/flags/pm.png new file mode 100644 index 000000000..ba91d2c7a Binary files /dev/null and b/deluge/data/pixmaps/flags/pm.png differ diff --git a/deluge/data/pixmaps/flags/pn.png b/deluge/data/pixmaps/flags/pn.png new file mode 100644 index 000000000..aa9344f57 Binary files /dev/null and b/deluge/data/pixmaps/flags/pn.png differ diff --git a/deluge/data/pixmaps/flags/pr.png b/deluge/data/pixmaps/flags/pr.png new file mode 100644 index 000000000..82d9130da Binary files /dev/null and b/deluge/data/pixmaps/flags/pr.png differ diff --git a/deluge/data/pixmaps/flags/ps.png b/deluge/data/pixmaps/flags/ps.png new file mode 100644 index 000000000..f5f547762 Binary files /dev/null and b/deluge/data/pixmaps/flags/ps.png differ diff --git a/deluge/data/pixmaps/flags/pt.png b/deluge/data/pixmaps/flags/pt.png new file mode 100644 index 000000000..ece798015 Binary files /dev/null and b/deluge/data/pixmaps/flags/pt.png differ diff --git a/deluge/data/pixmaps/flags/pw.png b/deluge/data/pixmaps/flags/pw.png new file mode 100644 index 000000000..6178b254a Binary files /dev/null and b/deluge/data/pixmaps/flags/pw.png differ diff --git a/deluge/data/pixmaps/flags/py.png b/deluge/data/pixmaps/flags/py.png new file mode 100644 index 000000000..cb8723c06 Binary files /dev/null and b/deluge/data/pixmaps/flags/py.png differ diff --git a/deluge/data/pixmaps/flags/qa.png b/deluge/data/pixmaps/flags/qa.png new file mode 100644 index 000000000..ed4c621fa Binary files /dev/null and b/deluge/data/pixmaps/flags/qa.png differ diff --git a/deluge/data/pixmaps/flags/re.png b/deluge/data/pixmaps/flags/re.png new file mode 100644 index 000000000..8332c4ec2 Binary files /dev/null and b/deluge/data/pixmaps/flags/re.png differ diff --git a/deluge/data/pixmaps/flags/ro.png b/deluge/data/pixmaps/flags/ro.png new file mode 100644 index 000000000..57e74a651 Binary files /dev/null and b/deluge/data/pixmaps/flags/ro.png differ diff --git a/deluge/data/pixmaps/flags/rs.png b/deluge/data/pixmaps/flags/rs.png new file mode 100644 index 000000000..9439a5b60 Binary files /dev/null and b/deluge/data/pixmaps/flags/rs.png differ diff --git a/deluge/data/pixmaps/flags/ru.png b/deluge/data/pixmaps/flags/ru.png new file mode 100644 index 000000000..47da4214f Binary files /dev/null and b/deluge/data/pixmaps/flags/ru.png differ diff --git a/deluge/data/pixmaps/flags/rw.png b/deluge/data/pixmaps/flags/rw.png new file mode 100644 index 000000000..535649178 Binary files /dev/null and b/deluge/data/pixmaps/flags/rw.png differ diff --git a/deluge/data/pixmaps/flags/sa.png b/deluge/data/pixmaps/flags/sa.png new file mode 100644 index 000000000..b4641c7e8 Binary files /dev/null and b/deluge/data/pixmaps/flags/sa.png differ diff --git a/deluge/data/pixmaps/flags/sb.png b/deluge/data/pixmaps/flags/sb.png new file mode 100644 index 000000000..a9937ccf0 Binary files /dev/null and b/deluge/data/pixmaps/flags/sb.png differ diff --git a/deluge/data/pixmaps/flags/sc.png b/deluge/data/pixmaps/flags/sc.png new file mode 100644 index 000000000..39ee37184 Binary files /dev/null and b/deluge/data/pixmaps/flags/sc.png differ diff --git a/deluge/data/pixmaps/flags/sd.png b/deluge/data/pixmaps/flags/sd.png new file mode 100644 index 000000000..eaab69eb7 Binary files /dev/null and b/deluge/data/pixmaps/flags/sd.png differ diff --git a/deluge/data/pixmaps/flags/se.png b/deluge/data/pixmaps/flags/se.png new file mode 100644 index 000000000..1994653da Binary files /dev/null and b/deluge/data/pixmaps/flags/se.png differ diff --git a/deluge/data/pixmaps/flags/sg.png b/deluge/data/pixmaps/flags/sg.png new file mode 100644 index 000000000..dd34d6121 Binary files /dev/null and b/deluge/data/pixmaps/flags/sg.png differ diff --git a/deluge/data/pixmaps/flags/sh.png b/deluge/data/pixmaps/flags/sh.png new file mode 100644 index 000000000..4b1d2a291 Binary files /dev/null and b/deluge/data/pixmaps/flags/sh.png differ diff --git a/deluge/data/pixmaps/flags/si.png b/deluge/data/pixmaps/flags/si.png new file mode 100644 index 000000000..bb1476ff5 Binary files /dev/null and b/deluge/data/pixmaps/flags/si.png differ diff --git a/deluge/data/pixmaps/flags/sj.png b/deluge/data/pixmaps/flags/sj.png new file mode 100644 index 000000000..160b6b5b7 Binary files /dev/null and b/deluge/data/pixmaps/flags/sj.png differ diff --git a/deluge/data/pixmaps/flags/sk.png b/deluge/data/pixmaps/flags/sk.png new file mode 100644 index 000000000..7ccbc8274 Binary files /dev/null and b/deluge/data/pixmaps/flags/sk.png differ diff --git a/deluge/data/pixmaps/flags/sl.png b/deluge/data/pixmaps/flags/sl.png new file mode 100644 index 000000000..12d812d29 Binary files /dev/null and b/deluge/data/pixmaps/flags/sl.png differ diff --git a/deluge/data/pixmaps/flags/sm.png b/deluge/data/pixmaps/flags/sm.png new file mode 100644 index 000000000..3df2fdcf8 Binary files /dev/null and b/deluge/data/pixmaps/flags/sm.png differ diff --git a/deluge/data/pixmaps/flags/sn.png b/deluge/data/pixmaps/flags/sn.png new file mode 100644 index 000000000..eabb71db4 Binary files /dev/null and b/deluge/data/pixmaps/flags/sn.png differ diff --git a/deluge/data/pixmaps/flags/so.png b/deluge/data/pixmaps/flags/so.png new file mode 100644 index 000000000..4a1ea4b29 Binary files /dev/null and b/deluge/data/pixmaps/flags/so.png differ diff --git a/deluge/data/pixmaps/flags/sr.png b/deluge/data/pixmaps/flags/sr.png new file mode 100644 index 000000000..5eff9271d Binary files /dev/null and b/deluge/data/pixmaps/flags/sr.png differ diff --git a/deluge/data/pixmaps/flags/st.png b/deluge/data/pixmaps/flags/st.png new file mode 100644 index 000000000..2978557b1 Binary files /dev/null and b/deluge/data/pixmaps/flags/st.png differ diff --git a/deluge/data/pixmaps/flags/sv.png b/deluge/data/pixmaps/flags/sv.png new file mode 100644 index 000000000..24987990b Binary files /dev/null and b/deluge/data/pixmaps/flags/sv.png differ diff --git a/deluge/data/pixmaps/flags/sy.png b/deluge/data/pixmaps/flags/sy.png new file mode 100644 index 000000000..f5ce30dcb Binary files /dev/null and b/deluge/data/pixmaps/flags/sy.png differ diff --git a/deluge/data/pixmaps/flags/sz.png b/deluge/data/pixmaps/flags/sz.png new file mode 100644 index 000000000..914ee861d Binary files /dev/null and b/deluge/data/pixmaps/flags/sz.png differ diff --git a/deluge/data/pixmaps/flags/tc.png b/deluge/data/pixmaps/flags/tc.png new file mode 100644 index 000000000..8fc1156be Binary files /dev/null and b/deluge/data/pixmaps/flags/tc.png differ diff --git a/deluge/data/pixmaps/flags/td.png b/deluge/data/pixmaps/flags/td.png new file mode 100644 index 000000000..667f21fd9 Binary files /dev/null and b/deluge/data/pixmaps/flags/td.png differ diff --git a/deluge/data/pixmaps/flags/tf.png b/deluge/data/pixmaps/flags/tf.png new file mode 100644 index 000000000..80529a436 Binary files /dev/null and b/deluge/data/pixmaps/flags/tf.png differ diff --git a/deluge/data/pixmaps/flags/tg.png b/deluge/data/pixmaps/flags/tg.png new file mode 100644 index 000000000..3aa00ad4d Binary files /dev/null and b/deluge/data/pixmaps/flags/tg.png differ diff --git a/deluge/data/pixmaps/flags/th.png b/deluge/data/pixmaps/flags/th.png new file mode 100644 index 000000000..dd8ba9171 Binary files /dev/null and b/deluge/data/pixmaps/flags/th.png differ diff --git a/deluge/data/pixmaps/flags/tj.png b/deluge/data/pixmaps/flags/tj.png new file mode 100644 index 000000000..617bf6455 Binary files /dev/null and b/deluge/data/pixmaps/flags/tj.png differ diff --git a/deluge/data/pixmaps/flags/tk.png b/deluge/data/pixmaps/flags/tk.png new file mode 100644 index 000000000..67b8c8cb5 Binary files /dev/null and b/deluge/data/pixmaps/flags/tk.png differ diff --git a/deluge/data/pixmaps/flags/tl.png b/deluge/data/pixmaps/flags/tl.png new file mode 100644 index 000000000..77da181e9 Binary files /dev/null and b/deluge/data/pixmaps/flags/tl.png differ diff --git a/deluge/data/pixmaps/flags/tm.png b/deluge/data/pixmaps/flags/tm.png new file mode 100644 index 000000000..828020ecd Binary files /dev/null and b/deluge/data/pixmaps/flags/tm.png differ diff --git a/deluge/data/pixmaps/flags/tn.png b/deluge/data/pixmaps/flags/tn.png new file mode 100644 index 000000000..183cdd3dc Binary files /dev/null and b/deluge/data/pixmaps/flags/tn.png differ diff --git a/deluge/data/pixmaps/flags/to.png b/deluge/data/pixmaps/flags/to.png new file mode 100644 index 000000000..f89b8ba75 Binary files /dev/null and b/deluge/data/pixmaps/flags/to.png differ diff --git a/pixmaps/flags18x12/tp.png b/deluge/data/pixmaps/flags/tp.png similarity index 100% rename from pixmaps/flags18x12/tp.png rename to deluge/data/pixmaps/flags/tp.png diff --git a/deluge/data/pixmaps/flags/tr.png b/deluge/data/pixmaps/flags/tr.png new file mode 100644 index 000000000..be32f77e9 Binary files /dev/null and b/deluge/data/pixmaps/flags/tr.png differ diff --git a/deluge/data/pixmaps/flags/tt.png b/deluge/data/pixmaps/flags/tt.png new file mode 100644 index 000000000..2a11c1e20 Binary files /dev/null and b/deluge/data/pixmaps/flags/tt.png differ diff --git a/deluge/data/pixmaps/flags/tv.png b/deluge/data/pixmaps/flags/tv.png new file mode 100644 index 000000000..28274c5fb Binary files /dev/null and b/deluge/data/pixmaps/flags/tv.png differ diff --git a/deluge/data/pixmaps/flags/tw.png b/deluge/data/pixmaps/flags/tw.png new file mode 100644 index 000000000..f31c654c9 Binary files /dev/null and b/deluge/data/pixmaps/flags/tw.png differ diff --git a/deluge/data/pixmaps/flags/tz.png b/deluge/data/pixmaps/flags/tz.png new file mode 100644 index 000000000..c00ff7961 Binary files /dev/null and b/deluge/data/pixmaps/flags/tz.png differ diff --git a/deluge/data/pixmaps/flags/ua.png b/deluge/data/pixmaps/flags/ua.png new file mode 100644 index 000000000..09563a219 Binary files /dev/null and b/deluge/data/pixmaps/flags/ua.png differ diff --git a/deluge/data/pixmaps/flags/ug.png b/deluge/data/pixmaps/flags/ug.png new file mode 100644 index 000000000..33f4affad Binary files /dev/null and b/deluge/data/pixmaps/flags/ug.png differ diff --git a/deluge/data/pixmaps/flags/um.png b/deluge/data/pixmaps/flags/um.png new file mode 100644 index 000000000..c1dd9654b Binary files /dev/null and b/deluge/data/pixmaps/flags/um.png differ diff --git a/deluge/data/pixmaps/flags/us.png b/deluge/data/pixmaps/flags/us.png new file mode 100644 index 000000000..10f451fe8 Binary files /dev/null and b/deluge/data/pixmaps/flags/us.png differ diff --git a/deluge/data/pixmaps/flags/uy.png b/deluge/data/pixmaps/flags/uy.png new file mode 100644 index 000000000..31d948a06 Binary files /dev/null and b/deluge/data/pixmaps/flags/uy.png differ diff --git a/deluge/data/pixmaps/flags/uz.png b/deluge/data/pixmaps/flags/uz.png new file mode 100644 index 000000000..fef5dc170 Binary files /dev/null and b/deluge/data/pixmaps/flags/uz.png differ diff --git a/deluge/data/pixmaps/flags/va.png b/deluge/data/pixmaps/flags/va.png new file mode 100644 index 000000000..b31eaf225 Binary files /dev/null and b/deluge/data/pixmaps/flags/va.png differ diff --git a/deluge/data/pixmaps/flags/vc.png b/deluge/data/pixmaps/flags/vc.png new file mode 100644 index 000000000..8fa17b061 Binary files /dev/null and b/deluge/data/pixmaps/flags/vc.png differ diff --git a/deluge/data/pixmaps/flags/ve.png b/deluge/data/pixmaps/flags/ve.png new file mode 100644 index 000000000..00c90f9af Binary files /dev/null and b/deluge/data/pixmaps/flags/ve.png differ diff --git a/deluge/data/pixmaps/flags/vg.png b/deluge/data/pixmaps/flags/vg.png new file mode 100644 index 000000000..415690798 Binary files /dev/null and b/deluge/data/pixmaps/flags/vg.png differ diff --git a/deluge/data/pixmaps/flags/vi.png b/deluge/data/pixmaps/flags/vi.png new file mode 100644 index 000000000..ed26915a3 Binary files /dev/null and b/deluge/data/pixmaps/flags/vi.png differ diff --git a/deluge/data/pixmaps/flags/vn.png b/deluge/data/pixmaps/flags/vn.png new file mode 100644 index 000000000..ec7cd48a3 Binary files /dev/null and b/deluge/data/pixmaps/flags/vn.png differ diff --git a/deluge/data/pixmaps/flags/vu.png b/deluge/data/pixmaps/flags/vu.png new file mode 100644 index 000000000..b3397bc63 Binary files /dev/null and b/deluge/data/pixmaps/flags/vu.png differ diff --git a/deluge/data/pixmaps/flags/wf.png b/deluge/data/pixmaps/flags/wf.png new file mode 100644 index 000000000..9f9558734 Binary files /dev/null and b/deluge/data/pixmaps/flags/wf.png differ diff --git a/deluge/data/pixmaps/flags/ws.png b/deluge/data/pixmaps/flags/ws.png new file mode 100644 index 000000000..c16950802 Binary files /dev/null and b/deluge/data/pixmaps/flags/ws.png differ diff --git a/deluge/data/pixmaps/flags/ye.png b/deluge/data/pixmaps/flags/ye.png new file mode 100644 index 000000000..468dfad03 Binary files /dev/null and b/deluge/data/pixmaps/flags/ye.png differ diff --git a/deluge/data/pixmaps/flags/yt.png b/deluge/data/pixmaps/flags/yt.png new file mode 100644 index 000000000..c298f378b Binary files /dev/null and b/deluge/data/pixmaps/flags/yt.png differ diff --git a/pixmaps/flags18x12/yu.png b/deluge/data/pixmaps/flags/yu.png similarity index 100% rename from pixmaps/flags18x12/yu.png rename to deluge/data/pixmaps/flags/yu.png diff --git a/deluge/data/pixmaps/flags/za.png b/deluge/data/pixmaps/flags/za.png new file mode 100644 index 000000000..57c58e211 Binary files /dev/null and b/deluge/data/pixmaps/flags/za.png differ diff --git a/deluge/data/pixmaps/flags/zm.png b/deluge/data/pixmaps/flags/zm.png new file mode 100644 index 000000000..c25b07bee Binary files /dev/null and b/deluge/data/pixmaps/flags/zm.png differ diff --git a/deluge/data/pixmaps/flags/zw.png b/deluge/data/pixmaps/flags/zw.png new file mode 100644 index 000000000..53c97259b Binary files /dev/null and b/deluge/data/pixmaps/flags/zw.png differ diff --git a/deluge/data/pixmaps/inactive.svg b/deluge/data/pixmaps/inactive.svg new file mode 100644 index 000000000..5edd9bece --- /dev/null +++ b/deluge/data/pixmaps/inactive.svg @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Internet Category + + + Jakub Steiner + + + + + Tuomas Kuosmanen + + + + http://jimmac.musichall.cz + + + internet + tools + applications + category + + + + + + + + + + + + + + + + + + + + + + diff --git a/pixmaps/inactive16.png b/deluge/data/pixmaps/inactive16.png similarity index 100% rename from pixmaps/inactive16.png rename to deluge/data/pixmaps/inactive16.png diff --git a/deluge/data/pixmaps/queued.svg b/deluge/data/pixmaps/queued.svg new file mode 100644 index 000000000..6206803e5 --- /dev/null +++ b/deluge/data/pixmaps/queued.svg @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Internet Category + + + Jakub Steiner + + + + + Tuomas Kuosmanen + + + + http://jimmac.musichall.cz + + + internet + tools + applications + category + + + + + + + + + + + + + + + + + + + diff --git a/deluge/data/pixmaps/queued16.png b/deluge/data/pixmaps/queued16.png new file mode 100644 index 000000000..551432f85 Binary files /dev/null and b/deluge/data/pixmaps/queued16.png differ diff --git a/deluge/data/pixmaps/seeding.svg b/deluge/data/pixmaps/seeding.svg new file mode 100644 index 000000000..0e32ddac2 --- /dev/null +++ b/deluge/data/pixmaps/seeding.svg @@ -0,0 +1,350 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Internet Category + + + Jakub Steiner + + + + + Tuomas Kuosmanen + + + + http://jimmac.musichall.cz + + + internet + tools + applications + category + + + + + + + + + + + + + + + + + + + diff --git a/pixmaps/seeding16.png b/deluge/data/pixmaps/seeding16.png similarity index 100% rename from pixmaps/seeding16.png rename to deluge/data/pixmaps/seeding16.png diff --git a/deluge/data/revision b/deluge/data/revision new file mode 100644 index 000000000..e69de29bb diff --git a/deluge/data/share/applications/deluge.desktop b/deluge/data/share/applications/deluge.desktop new file mode 100644 index 000000000..068855dc3 --- /dev/null +++ b/deluge/data/share/applications/deluge.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Version=1.0 +Name=Deluge +GenericName=Bittorrent Client +Comment=Transfer files using the Bittorrent protocol +Exec=deluge +Icon=deluge +Terminal=false +Type=Application +Categories=Network; +StartupNotify=true +MimeType=application/x-bittorrent; diff --git a/deluge/error.py b/deluge/error.py new file mode 100644 index 000000000..256962366 --- /dev/null +++ b/deluge/error.py @@ -0,0 +1,42 @@ +# +# error.py +# +# Copyright (C) 2008 Andrew Resch ('andar') +# +# 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 2 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. + +class DelugeError(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + +class NoCoreError(DelugeError): + pass + diff --git a/deluge/i18n/POTFILES.in b/deluge/i18n/POTFILES.in new file mode 100644 index 000000000..c57610893 --- /dev/null +++ b/deluge/i18n/POTFILES.in @@ -0,0 +1,18 @@ +deluge/ui/gtkui/glade/main_window.glade +deluge/ui/gtkui/glade/preferences_dialog.glade +deluge/plugins/queue/queue/gtkui.py +deluge/ui/gtkui/torrentview.py +deluge/core/torrentmanager.py +deluge/ui/webui/webui_plugin/config.py +deluge/ui/webui/webui_plugin/config_tabs_deluge.py +deluge/ui/webui/webui_plugin/config_tabs_webui.py +deluge/ui/webui/webui_plugin/dbus_interface.py +deluge/ui/webui/webui_plugin/debugerror.py +deluge/ui/webui/webui_plugin/deluge_webserver.py +deluge/ui/webui/webui_plugin/page_decorators.py +deluge/ui/webui/webui_plugin/pages.py +deluge/ui/webui/webui_plugin/render.py +deluge/ui/webui/webui_plugin/scripts/template_strings.py +deluge/ui/webui/webui_plugin/torrent_add.py +deluge/ui/webui/webui_plugin/utils.py +deluge/ui/webui/webui_plugin/webserver_common.py diff --git a/deluge/i18n/deluge.pot b/deluge/i18n/deluge.pot new file mode 100644 index 000000000..710d02109 --- /dev/null +++ b/deluge/i18n/deluge.pot @@ -0,0 +1,621 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-10-01 22:01-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: deluge/ui/gtkui/glade/main_window.glade:20 +msgid "_File" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:27 +msgid "_Add Torrent" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:42 +msgid "Add _URL" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:50 +msgid "_Clear Completed" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:70 +msgid "Quit & Shutdown Daemon" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:102 +msgid "_Edit" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:123 +msgid "_Torrent" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:130 +msgid "_View" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:138 +msgid "_Toolbar" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:146 +msgid "_Details" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:154 +msgid "_Columns" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:165 +msgid "_Help" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:194 +msgid "Add torrent" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:195 +msgid "Add Torrent" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:207 +msgid "Remove the selected torrents" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:208 +msgid "Remove Torrent" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:220 +msgid "Remove the finished torrents" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:221 +msgid "Clear Finished" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:242 +msgid "Pause the selected torrents" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:243 +msgid "Pause" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:256 +msgid "Resume the selected torrents" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:257 +msgid "Resume" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:277 +#: deluge/ui/gtkui/glade/main_window.glade:278 +msgid "Preferences" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:482 +msgid "Downloaded:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:496 +msgid "Uploaded:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:514 +msgid "Seeders:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:532 +msgid "Share Ratio:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:551 +#: deluge/ui/gtkui/glade/main_window.glade:570 +msgid "Speed:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:591 +msgid "Peers:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:612 +msgid "ETA:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:629 +msgid "Pieces:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:667 +msgid "Availability:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:708 +msgid "Statistics" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:750 +msgid "# of files:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:810 +msgid "Total Size:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:836 +msgid "Tracker:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:864 +msgid "Tracker Status:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:887 +msgid "Next Announce:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:909 +msgid "Name:" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:967 +msgid "Torrent Info" +msgstr "" + +#: deluge/ui/gtkui/glade/main_window.glade:993 +msgid "Details" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:8 +msgid "Deluge Preferences" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:74 +msgid "Downloads" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:108 +msgid "Ask where to save each download" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:124 +#: deluge/ui/gtkui/glade/preferences_dialog.glade:125 +msgid "Store all downloads in:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:142 +msgid "Select A Folder" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:161 +msgid "Download Location" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:197 +msgid "" +"Full allocation preallocates all of the space that is needed for the torrent " +"and prevents disk fragmentation" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:198 +msgid "Use Full Allocation" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:213 +msgid "Compact allocation only allocates space as needed" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:214 +msgid "Use Compact Allocation" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:232 +msgid "Allocation" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:266 +#: deluge/ui/gtkui/glade/preferences_dialog.glade:267 +msgid "Enable selecting files for torrents before loading" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:280 +#: deluge/ui/gtkui/glade/preferences_dialog.glade:281 +msgid "Prioritize first and last pieces of files in torrent" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:297 +msgid "Torrents" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:350 +msgid "Network" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:387 +msgid "From:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:414 +msgid "To:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:445 +msgid "Test Active Port" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:470 +msgid "Deluge will automatically choose a different port to use every time." +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:471 +msgid "Use Random Ports" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:489 +msgid "Active Port:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:501 +msgid "0000" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:531 +msgid "Ports" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:563 +msgid "Distributed hash table may improve the amount of active connections." +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:564 +msgid "Enable Mainline DHT" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:577 +msgid "DHT" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:610 +msgid "Universal Plug and Play" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:611 +msgid "UPnP" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:626 +msgid "NAT Port Mapping Protocol" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:627 +msgid "NAT-PMP" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:643 +msgid "µTorrent Peer-Exchange" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:644 +msgid "µTorrent-PeX" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:663 +msgid "Network Extras" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:699 +msgid "Inbound:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:708 +#: deluge/ui/gtkui/glade/preferences_dialog.glade:732 +msgid "" +"Forced\n" +"Enabled\n" +"Disabled" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:722 +msgid "Outbound:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:751 +msgid "Level:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:760 +msgid "" +"Handshake\n" +"Full Stream\n" +"Either" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:779 +msgid "Prefer to encrypt the entire stream" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:796 +msgid "Encryption" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:850 +msgid "Bandwidth" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:889 +msgid "The maximum upload slots for all torrents. Set -1 for unlimited." +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:908 +#: deluge/ui/gtkui/glade/preferences_dialog.glade:978 +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1002 +msgid "The maximum upload speed for all torrents. Set -1 for unlimited." +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:928 +#: deluge/ui/gtkui/glade/preferences_dialog.glade:946 +msgid "The maximum download speed for all torrents. Set -1 for unlimited." +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:948 +msgid "Maximum Download Speed (KiB/s):" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:960 +#: deluge/ui/gtkui/glade/preferences_dialog.glade:991 +msgid "The maximum number of connections allowed. Set -1 for unlimited." +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:980 +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1105 +msgid "Maximum Upload Slots:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:993 +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1094 +msgid "Maximum Connections:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1004 +msgid "Maximum Upload Speed (KiB/s):" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1019 +msgid "Global Bandwidth Usage" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1058 +msgid "The maximum upload slots per torrent. Set -1 for unlimited." +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1077 +msgid "The maximum number of connections per torrent. Set -1 for unlimited." +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1121 +msgid "Per Torrent Bandwidth Usage" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1175 +msgid "Other" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1209 +msgid "Enable system tray icon" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1224 +msgid "Minimize to tray on close" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1243 +msgid "Start in tray" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1264 +msgid "Password protect system tray" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1291 +msgid "Password:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1325 +msgid "System Tray" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1363 +msgid "Open folder with:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1378 +msgid "Custom:" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1395 +msgid "" +"Auto-detect (xdg-open)\n" +"Konqueror\n" +"Nautilus\n" +"Thunar" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1437 +msgid "Desktop File Manager" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1477 +msgid "" +"Deluge will check our servers and will tell you if a newer version has been " +"released" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1478 +msgid "Be alerted about new releases" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1497 +msgid "Updates" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1533 +msgid "" +"Help us improve Deluge by sending us your Python version, PyGTK version, OS " +"and processor types. Absolutely no other information is sent." +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1552 +msgid "Yes, please send anonymous statistics" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1571 +msgid "System Information" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1625 +msgid "Plugins" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1717 +msgid "gtk-cancel" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1729 +msgid "gtk-apply" +msgstr "" + +#: deluge/ui/gtkui/glade/preferences_dialog.glade:1744 +msgid "gtk-ok" +msgstr "" + +#: deluge/plugins/queue/queue/gtkui.py:100 +msgid "Queue Up" +msgstr "" + +#: deluge/plugins/queue/queue/gtkui.py:101 +msgid "Queue selected torrents up" +msgstr "" + +#: deluge/plugins/queue/queue/gtkui.py:105 +msgid "Queue Down" +msgstr "" + +#: deluge/plugins/queue/queue/gtkui.py:106 +msgid "Queue selected torrents down" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:75 +msgid "Queued" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:76 +msgid "Checking" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:77 +msgid "Connecting" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:78 +msgid "Downloading Metadata" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:79 +msgid "Downloading" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:80 +msgid "Finished" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:81 +msgid "Seeding" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:82 +msgid "Allocating" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:83 +msgid "Paused" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:115 +msgid "Name" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:117 +msgid "Size" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:121 +msgid "Progress" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:125 +msgid "Seeders" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:130 +msgid "Peers" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:135 +msgid "Down Speed" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:139 +msgid "Up Speed" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:143 +msgid "ETA" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:147 +msgid "Ratio" +msgstr "" + +#: deluge/ui/gtkui/torrentview.py:151 +msgid "Avail" +msgstr "" + +#: deluge/core/torrentmanager.py:381 +msgid "Announce OK" +msgstr "" + +#: deluge/core/torrentmanager.py:388 +msgid "Announce Sent" +msgstr "" + +#: deluge/core/torrentmanager.py:395 +msgid "Alert" +msgstr "" + +#: deluge/core/torrentmanager.py:396 +msgid "HTTP code" +msgstr "" + +#: deluge/core/torrentmanager.py:397 +msgid "times in a row" +msgstr "" + +#: deluge/core/torrentmanager.py:405 +msgid "Warning" +msgstr "" diff --git a/deluge/log.py b/deluge/log.py new file mode 100644 index 000000000..2b74c62a9 --- /dev/null +++ b/deluge/log.py @@ -0,0 +1,46 @@ +# +# log.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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. + +"""Logging functions""" + +import logging + +# Setup the logger +logging.basicConfig( + level=logging.DEBUG, + format="[%(levelname)-8s] %(asctime)s %(module)s:%(lineno)d %(message)s", + datefmt="%H:%M:%S" +) + +# Get the logger +LOG = logging.getLogger("deluge") diff --git a/deluge/main.py b/deluge/main.py new file mode 100644 index 000000000..df92d2818 --- /dev/null +++ b/deluge/main.py @@ -0,0 +1,131 @@ +# +# main.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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. + +# The main starting point for the program. This function is called when the +# user runs the command 'deluge'. + +"""Main starting point for Deluge. Contains the main() entry point.""" + +import os +import os.path +import sys +from optparse import OptionParser + +import deluge.common + +def start_ui(): + """Entry point for ui script""" + # Setup the argument parser + parser = OptionParser(usage="%prog [options] [actions]", + version=deluge.common.get_version()) + + parser.add_option("-u", "--ui", dest="ui", + help="The UI that you wish to launch", action="store", type="str") + parser.add_option("-c", "--config", dest="config", + help="Set the config location", action="store", type="str") + parser.add_option("-l", "--logfile", dest="logfile", + help="Output to designated logfile instead of stdout", action="store", type="str") + + # Get the options and args from the OptionParser + (options, args) = parser.parse_args() + + if deluge.common.windows_check(): + if options.config: + os.makedirs(options.config) + logfile = os.path.join(options.config, "deluge.log") + else: + os.makedirs(deluge.common.get_default_config_dir()) + logfile = deluge.common.get_default_config_dir("deluge.log") + + sys.stdout = open(logfile, "wb") + sys.stderr = sys.stdout + sys.stdin = None + + from deluge.log import LOG as log + + version = deluge.common.get_version() + if deluge.common.get_revision() != "": + version = version + "r" + deluge.common.get_revision() + + log.info("Deluge ui %s", version) + log.debug("options: %s", options) + log.debug("args: %s", args) + + from deluge.ui.ui import UI + log.info("Starting ui..") + UI(options, args) + +def start_daemon(): + """Entry point for daemon script""" + import deluge.common + + # Setup the argument parser + parser = OptionParser(usage="%prog [options] [actions]", + version=deluge.common.get_version()) + parser.add_option("-p", "--port", dest="port", + help="Port daemon will listen on", action="store", type="int") + 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", + help="Set the config location", action="store", type="str") + parser.add_option("-l", "--logfile", dest="logfile", + help="Set the logfile location", action="store", type="str") + + # Get the options and args from the OptionParser + (options, args) = parser.parse_args() + + # If the donot daemonize is set, then we just skip the forking + if not options.donot and not deluge.common.windows_check(): + if os.fork() == 0: + os.setsid() + if os.fork() == 0: + if options.logfile: + logfile = options.logfile + else: + if options.config: + logfile = os.path.join(options.config, "deluged.log") + else: + config_dir = deluge.common.get_default_config_dir() + logfile = os.path.join(config_dir, "deluged.log") + + sys.stdout = open(logfile, "w") + sys.stderr = sys.stdout + sys.stdin = None + else: + os._exit(0) + else: + os._exit(0) + + from deluge.core.daemon import Daemon + Daemon(options, args) + diff --git a/deluge/pluginmanagerbase.py b/deluge/pluginmanagerbase.py new file mode 100644 index 000000000..92f007191 --- /dev/null +++ b/deluge/pluginmanagerbase.py @@ -0,0 +1,129 @@ +# +# pluginmanagerbase.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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. + +"""PluginManagerBase""" + +import os.path + +import pkg_resources + +import deluge.common +import deluge.configmanager +from deluge.log import LOG as log + +class PluginManagerBase: + """PluginManagerBase is a base class for PluginManagers to inherit""" + + def __init__(self, config_file, entry_name): + log.debug("Plugin manager init..") + + self.config = deluge.configmanager.ConfigManager(config_file) + + # This is the entry we want to load.. + self.entry_name = entry_name + + # Loaded plugins + self.plugins = {} + + # Scan the plugin folders for plugins + self.scan_for_plugins() + + def enable_plugins(self): + # Load plugins that are enabled in the config. + for name in self.config["enabled_plugins"]: + self.enable_plugin(name) + + def disable_plugins(self): + # Disable all plugins that are enabled + for key in self.plugins.keys(): + self.plugins[key].disable() + + def __getitem__(self, key): + return self.plugins[key] + + def get_available_plugins(self): + """Returns a list of the available plugins name""" + return self.available_plugins + + def get_enabled_plugins(self): + """Returns a list of enabled plugins""" + return self.plugins.keys() + + def scan_for_plugins(self): + """Scans for available plugins""" + plugin_dir = os.path.join(os.path.dirname(__file__), "plugins") + user_plugin_dir = os.path.join(deluge.configmanager.get_config_dir(), "plugins") + + pkg_resources.working_set.add_entry(plugin_dir) + pkg_resources.working_set.add_entry(user_plugin_dir) + self.pkg_env = pkg_resources.Environment([plugin_dir, user_plugin_dir]) + + self.available_plugins = [] + for name in self.pkg_env: + pkg_name = str(self.pkg_env[name][0]).split()[0].replace("-", " ") + pkg_version = str(self.pkg_env[name][0]).split()[1] + log.debug("Found plugin: %s %s", pkg_name, pkg_version) + self.available_plugins.append(pkg_name) + + def enable_plugin(self, plugin_name): + """Enables a plugin""" + if plugin_name not in self.available_plugins: + log.warning("Cannot enable non-existant plugin %s", plugin_name) + return + + plugin_name = plugin_name.replace(" ", "-") + egg = self.pkg_env[plugin_name][0] + 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() + instance = cls(self, plugin_name.replace("-", "_")) + instance.enable() + plugin_name = plugin_name.replace("-", " ") + self.plugins[plugin_name] = instance + if plugin_name not in self.config["enabled_plugins"]: + log.debug("Adding %s to enabled_plugins list in config", + plugin_name) + self.config["enabled_plugins"].append(plugin_name) + log.info("Plugin %s enabled..", plugin_name) + + def disable_plugin(self, name): + """Disables a plugin""" + try: + self.plugins[name].disable() + del self.plugins[name] + self.config["enabled_plugins"].remove(name) + except KeyError: + log.warning("Plugin %s is not enabled..", name) + + log.info("Plugin %s disabled..", name) diff --git a/deluge/plugins/__init__.py b/deluge/plugins/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/deluge/plugins/blocklist/blocklist/__init__.py b/deluge/plugins/blocklist/blocklist/__init__.py new file mode 100644 index 000000000..3baa6ea7e --- /dev/null +++ b/deluge/plugins/blocklist/blocklist/__init__.py @@ -0,0 +1,66 @@ +# +# blocklist/__init__.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# Copyright (C) 2008 Mark Stahler ('kramed') + +# +# 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 2 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.init import PluginBase + +class CorePlugin(PluginBase): + def __init__(self, plugin_api, plugin_name): + # Load the Core portion of the plugin + try: + from core import Core + self.plugin = Core(plugin_api, plugin_name) + except Exception, e: + log.debug("Did not load a Core plugin: %s", e) + +class GtkUIPlugin(PluginBase): + def __init__(self, plugin_api, plugin_name): + # Load the GtkUI portion of the plugin + try: + from gtkui import GtkUI + self.plugin = GtkUI(plugin_api, plugin_name) + except Exception, e: + log.debug("Did not load a GtkUI plugin: %s", e) + +class WebUIPlugin(PluginBase): + def __init__(self, plugin_api, plugin_name): + # Load the GtkUI portion of the plugin + try: + from webui import WebUI + self.plugin = WebUI(plugin_api, plugin_name) + except Exception, e: + log.debug("Did not load a WebUI plugin: %s", e) + diff --git a/deluge/plugins/blocklist/blocklist/core.py b/deluge/plugins/blocklist/blocklist/core.py new file mode 100644 index 000000000..3c3617c2c --- /dev/null +++ b/deluge/plugins/blocklist/blocklist/core.py @@ -0,0 +1,130 @@ +# +# blocklist/core.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# Copyright (C) 2008 Mark Stahler ('kramed') + +# +# 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 2 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 torrentblocklist import TorrentBlockList +from deluge.log import LOG as log +from deluge.plugins.corepluginbase import CorePluginBase + +class Core(CorePluginBase): + def enable(self): + self.blocklist = TorrentBlockList(self.plugin) + self.plugin.register_hook("post_session_load", self._post_session_load) + log.debug('Blocklist: Plugin enabled..') + + def disable(self): + log.debug('Blocklist: Plugin disabled') + self.plugin.deregister_hook("post_session_load", self._post_session_load) + self.plugin.reset_ip_filter() + # Delete the blocklist object + del self.blocklist + self.blocklist = None + + def update(self): + pass + + ## Hooks for core ## + def _post_session_load(self): + log.info('Blocklist: Session load hook caught') + if self.blocklist.load_on_start == True: + # Wait until an idle time to load block list + import gobject + gobject.idle_add(self.blocklist.import_list) + + ## Callbacks + def register_import_hook(self): + self.plugin.register_hook("post_session_load", self._post_session_load) + return False + + # Exported functions for ui + def export_critical_setting(self): + if self.blocklist.old_url != self.blocklist.url or self.blocklist.old_listtype != self.blocklist.listtype: + log.info('Blocklist: Critical setting changed') + self.blocklist.download() + self.blocklist.import_list() + self.blocklist.return_count() # Return count after import + + # New settings are now old settings + self.blocklist.old_url = self.blocklist.url + self.blocklist.old_listtype = self.blocklist.listtype + + def export_count_ips(self): + log.debug('Blocklist: Count IPs imported into blocklist') + return self.blocklist.return_count() + + def export_import_list(self): + log.debug('Blocklist: Import started from GTK UI') + self.blocklist.import_list() + + def export_download_list(self): + log.debug('Blocklist: Download started from GTK UI') + force_check = True + self.blocklist.check_update(force_check) + # Initialize download attempt + self.blocklist.attempt = 0 + + if self.blocklist.fetch == True: + self.blocklist.download() + + + def export_set_options(self, settings): + log.debug("Blocklist: Set Options") + self.blocklist.set_options(settings) + + def export_get_options(self): + log.debug("Blocklist: Get Options") + settings_dict = { + "url": self.blocklist.url, + "listtype": self.blocklist.listtype, + "check_after_days": self.blocklist.check_after_days, + "load_on_start":self.blocklist.load_on_start, + "try_times": self.blocklist.try_times, + "timeout": self.blocklist.timeout + } + log.info(settings_dict) + return settings_dict + + def export_get_config_value(self, key): + log.debug("Blocklist: Get configuration setting") + return self.blocklist.get_config_value(key) + + def export_set_config_value(self, key): + log.debug("Blocklist: Set configuration setting") + return self.blocklist.set_config_value(key) + + def export_get_formats(self): + log.debug('Blocklist: Get Reader Formats') + return self.blocklist.return_formats() + + \ No newline at end of file diff --git a/deluge/plugins/blocklist/blocklist/data/blocklist16.png b/deluge/plugins/blocklist/blocklist/data/blocklist16.png new file mode 100644 index 000000000..58240de7d Binary files /dev/null and b/deluge/plugins/blocklist/blocklist/data/blocklist16.png differ diff --git a/deluge/plugins/blocklist/blocklist/data/blocklist_download24.png b/deluge/plugins/blocklist/blocklist/data/blocklist_download24.png new file mode 100644 index 000000000..de73891d9 Binary files /dev/null and b/deluge/plugins/blocklist/blocklist/data/blocklist_download24.png differ diff --git a/deluge/plugins/blocklist/blocklist/data/blocklist_import24.png b/deluge/plugins/blocklist/blocklist/data/blocklist_import24.png new file mode 100644 index 000000000..ed2c75b22 Binary files /dev/null and b/deluge/plugins/blocklist/blocklist/data/blocklist_import24.png differ diff --git a/deluge/plugins/blocklist/blocklist/gtkui.py b/deluge/plugins/blocklist/blocklist/gtkui.py new file mode 100644 index 000000000..455f3fe2b --- /dev/null +++ b/deluge/plugins/blocklist/blocklist/gtkui.py @@ -0,0 +1,324 @@ +# +# blocklist/gtkui.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# Copyright (C) 2008 Mark Stahler ('kramed') + +# +# 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 2 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 os +import pkg_resources # access plugin egg +from deluge.log import LOG as log +import deluge.component # for systray +import ui +import gtk, gobject + +FORMATS = { + 'gzmule': ["Emule IP list (GZip)", None], + 'spzip': ["SafePeer Text (Zipped)", None], + 'pgtext': ["PeerGuardian Text (Uncompressed)", None], + 'p2bgz': ["PeerGuardian P2B (GZip)", None] +} + +class GtkUI(ui.UI): + def __init__(self, plugin_api, plugin_name): + log.debug("Calling UI init") + # Call UI constructor + ui.UI.__init__(self, plugin_api, plugin_name) + log.debug("Blocklist GtkUI plugin initalized..") + + def enable(self): + self.plugin.register_hook("on_apply_prefs", self.apply_prefs) + + # Import File Format Readers from TorrentBlocklist + #ui.client.block_list_get_formats(self.callback_load_formats) # cant marshal classobj objects - wtf + + # Update Blocked IP status bar number - BETTER METHOD TO FOLLOW + # emit a blocklsit import signal + gobject.timeout_add(5000, self.get_ip_count) + gobject.timeout_add(10000, self.get_ip_count) + gobject.timeout_add(20000, self.get_ip_count) + + self.load_interface() + + def disable(self): + deluge.component.get("StatusBar").remove_item(self.blocklist_status) + self.plugin.deregister_hook("on_apply_prefs", self.apply_prefs) + self.plugin.remove_preferences_page("Blocklist") + + def get_pixmap(self, fname): + """Returns a pixmap file included with plugin""" + return pkg_resources.resource_filename("blocklist", os.path.join("data", fname)) + + def add_status_icon(self, ip_count): + try: + deluge.component.get("StatusBar").remove_item(self.blocklist_status) + except: + pass + # self, image=None, stock=None, text=None, callback=None + self.blocklist_status = deluge.component.get("StatusBar").add_item(self.get_pixmap("blocklist16.png"), None, str(ip_count) + " Blocked IP Ranges ", None) + + def get_ip_count(self): + ui.client.block_list_count_ips(self.add_status_icon) + return False + + def start_import(self, widget, data=None): + ui.client.block_list_import_list(None) + log.debug('Blocklist: Import button') + gobject.timeout_add(20000, self.get_ip_count) + + def download_list(self, widget, data=None): + self.apply_prefs() + ui.client.block_list_download_list(None) + log.debug('Blocklist: Download button') + + def unload_interface(self): + self.plugin.remove_preferences_page("Blocklist") + +# def get_active_text(combobox): +# model = combobox.get_model() +# active = combobox.get_active() +# if active < 0: +# return None +# return model[active][0] + + def load_interface(self): + log.debug("Beginning gtk pane initialization") + self.blocklist_pref_page = gtk.VBox(False, 3) + self.blocklist_pref_page.set_spacing(6) + + label = gtk.Label() + label.set_markup('' + 'General' + '') + + frame = gtk.Frame() + frame.set_shadow_type(gtk.SHADOW_NONE) + + alignment = gtk.Alignment(0.5, 0.5, 1, 1) + alignment.set_padding(8, 5, 5, 5) + + table = gtk.Table(8, 2, False) + table.set_col_spacings(8) + table.set_row_spacings(10) + + # First row + label0 = gtk.Label() + label0.set_text('Blocklist Type') + + ls = gtk.ListStore(gobject.TYPE_STRING, # Long name + gobject.TYPE_STRING) # Short name + + self.listtype = gtk.ComboBox(model=ls) + cell = gtk.CellRendererText() + cell.set_property('xpad', 5) # padding for status text + self.listtype.pack_start(cell, False) + self.listtype.add_attribute(cell, 'text', 0) + + for k in FORMATS.keys(): + i = ls.append([FORMATS[k][0], k]) + FORMATS[k][1] = ls.get_path(i) + + self.listtype.set_active(0) + + table.attach(label0, 0, 1, 0 , 1) + table.attach(self.listtype, 1, 2, 0, 1) + + # Second row + label1 = gtk.Label() + label1.set_text('Blocklist URL') + + self.url = gtk.Entry() + + table.attach(label1, 0, 1, 1, 2) + table.attach(self.url, 1, 2, 1, 2) + + # Third row + label2 = gtk.Label() + label2.set_text('Check for a new blocklist every') + + self.check_after_days = gtk.SpinButton(None, 1.0, 0) + self.check_after_days.set_increments(1, 3) + self.check_after_days.set_range(-1, 14) + + label3 = gtk.Label() + label3.set_text('days') + + hbox = gtk.HBox(False, 3) + hbox.pack_start(label2, False, True) + hbox.pack_start(self.check_after_days, False, False, 4) + hbox.pack_start(label3) + + alignment.add(table) + table.attach(hbox, 0, 2, 2, 3) + + # Fourth row + label4 = gtk.Label() + label4.set_text('Timeout to download new blocklist') + + self.timeout = gtk.SpinButton(None, 5.0, 0) + self.timeout.set_increments(5, 20) + self.timeout.set_range(15, 360) + + label5 = gtk.Label() + label5.set_text('seconds') + + hbox1 = gtk.HBox(False, 3) + hbox1.pack_start(label4, False, True) + hbox1.pack_start(self.timeout) + hbox1.pack_start(label5, False, True) + + table.attach(hbox1, 0, 2, 3, 4) + + # Fifth row + label5 = gtk.Label() + label5.set_text('Times to attempt download of new list') + + self.try_times = gtk.SpinButton(None, 1.0, 0) + self.try_times.set_increments(1, 2) + self.try_times.set_range(1, 5) + + hbox2 = gtk.HBox(False, 3) + hbox2.pack_start(label5, False, True) + hbox2.pack_start(self.try_times) + + table.attach(hbox2, 0, 2, 4, 5) + + # sixth row + self.load_on_start = gtk.CheckButton('Import blocklist on daemon startup') + table.attach(self.load_on_start, 0, 2, 5, 6) + + # download new list button + download_button = gtk.Button("_Download Blocklist", None, True) + download_button.connect("clicked", self.download_list, None) + + pixbuf = gtk.gdk.pixbuf_new_from_file(self.get_pixmap("blocklist_download24.png")) + image = gtk.image_new_from_pixbuf(pixbuf) + download_button.set_image(image) + table.attach(download_button, 0, 2, 6, 7) + + # import button (Check and possibly download) + import_button = gtk.Button("_Import Blocklist", None, True) + import_button.connect("clicked", self.start_import, None) + + pixbuf = gtk.gdk.pixbuf_new_from_file(self.get_pixmap("blocklist_import24.png")) + image = gtk.image_new_from_pixbuf(pixbuf) + import_button.set_image(image) + + table.attach(import_button, 0, 2, 7, 8) + + + # finish frame + frame.set_label_widget(label) + frame.add(alignment) + + self.blocklist_pref_page.pack_start(frame) + + # Add preferences page to preferences page + log.debug('Adding Blocklist Preferences page') + self.plugin.add_preferences_page("Blocklist", self.blocklist_pref_page) + + # Load settings from config and fill widgets with settings + log.debug('Starting to load blocklist preferences') + self.fetch_prefs() + log.debug('Finished loading blocklist preferences') + + + def fetch_prefs(self): # Fetch settings dictionary from plugin core and pass it to GTK ui settings + log.info('Blocklist: Fetching and loading Preferences via GTK ui') + ui.client.block_list_get_options(self.callback_load_prefs) + + def apply_prefs(self): + log.info('Blocklist: Preferences saved via Gtk ui') + settings_dict = { + "url": self.url.get_text(), + "listtype": self.get_ltype(), + "check_after_days": self.check_after_days.get_value_as_int(), + "load_on_start":self.load_on_start.get_active(), + "try_times": self.try_times.get_value_as_int(), + "timeout": self.timeout.get_value_as_int() + } + ui.client.block_list_set_options(None, settings_dict) + # Needs to go in another thread or wait until window is closed + #gobject.idle_add(self.call_critical_setting) + + def call_critical_setting(self): + ui.client.block_list_critical_setting(None) # This checks to see if url or listtype changed, if so download & import + self.get_ip_count() + + # GTK Gui Callback functions + def callback_load_prefs(self, dict): + log.info('Blocklist: Callback Load Prefs GTK ui') + self.settings_url(dict['url']) + self.settings_listtype(dict['listtype']) + self.settings_load(dict['load_on_start']) + self.settings_check_after_days(dict['check_after_days']) + self.settings_timeout(dict['timeout']) + self.settings_try_times(dict['try_times']) + + # Specific function to return proper listtype so we can save and open it again + def get_ltype(self): + ls = self.listtype.get_model() + log.debug(ls) + ltype = ls[self.listtype.get_active()][1] + log.debug(ltype) + return ltype + + # Settings functions + def settings_listtype(self, setting): + log.debug('Blocklist: listtype') + path = FORMATS[setting][1] + i = self.listtype.get_model().get_iter(path) + self.listtype.set_active_iter(i) + + def settings_url(self, setting): + log.debug('Blocklist: url') + self.url.set_text(setting) + + def settings_check_after_days(self, setting): + log.debug('Blocklist: days') + self.check_after_days.set_value(setting) + + def settings_load(self, setting): + log.debug('Blocklist: load_on_start') + log.info(setting) + if setting == True or setting == "True": + setting = 1 + else: + setting = 0 + self.load_on_start.set_active(setting) + + def settings_timeout(self, setting): + log.debug('Blocklist: timeout') + self.timeout.set_value(setting) + + def settings_try_times(self, setting): + log.debug('Blocklist: try times') + self.try_times.set_value(setting) + + \ No newline at end of file diff --git a/plugins/BlocklistImport/peerguardian.py b/deluge/plugins/blocklist/blocklist/peerguardian.py similarity index 89% rename from plugins/BlocklistImport/peerguardian.py rename to deluge/plugins/blocklist/blocklist/peerguardian.py index 94e1fec44..6a583ef5b 100644 --- a/plugins/BlocklistImport/peerguardian.py +++ b/deluge/plugins/blocklist/blocklist/peerguardian.py @@ -6,7 +6,6 @@ from exceptions import Exception from struct import unpack import gzip, socket -import ui class PGException(Exception): pass @@ -21,8 +20,7 @@ class PGReader: try: self.fd = gzip.open(filename, "rb") except IOError, e: - ui.GTKError(_("We were expecting a gzip file, but didn't get that, \ -or possibly the file is corrupt. Please edit your Blocklist preferences")) + print 'Blocklist: PGReader: Incorrect file type or list is corrupt' # 4 bytes, should be 0xffffffff buf = self.fd.read(4) diff --git a/plugins/BlocklistImport/text.py b/deluge/plugins/blocklist/blocklist/text.py similarity index 90% rename from plugins/BlocklistImport/text.py rename to deluge/plugins/blocklist/blocklist/text.py index 81a5fa3d9..522aabc06 100644 --- a/plugins/BlocklistImport/text.py +++ b/deluge/plugins/blocklist/blocklist/text.py @@ -9,7 +9,6 @@ import re, gzip, os from socket import inet_aton from struct import unpack from zipfile import ZipFile -import ui class TextException(Exception): pass @@ -34,7 +33,7 @@ class TextBase: match = self.re.search(txt) if not match: - ui.GTKError(_("Wrong file type or corrupted blocklist file.")) + print 'Blocklist: TextBase: Wrong file type or corrupted blocklist file.' try: g = match.groups() @@ -67,7 +66,7 @@ class TextReader(PGTextReader): try: PGTextReader.__init__(self, open(filename, 'r')) except: - ui.GTKError(_("Wrong file type or corrupted blocklist file.")) + print 'Wrong file type or corrupted blocklist file.' # Reads Emule style blocklists (aka nipfilter) @@ -85,7 +84,7 @@ class GZMuleReader(MuleReader): try: MuleReader.__init__(self, gzip.open(filename, "r")) except: - ui.GTKError(_("Wrong file type or corrupted blocklist file.")) + print 'Wrong file type or corrupted blocklist file.' # Reads zip files from SafePeer style files @@ -96,7 +95,7 @@ class PGZip(TextBase): try: self.zfd = ZipFile(filename, 'r') except: - ui.GTKError(_("Wrong file type or corrupted blocklist file.")) + print 'Blocklist: PGZip: Wrong file type or corrupted blocklist file.' else: self.files = self.zfd.namelist() self.opennext() @@ -126,7 +125,7 @@ class PGZip(TextBase): return ret except FormatException, e: - ui.GTKError(_("Got format exception for zipfile:",e)) + print 'Blocklist: PGZip: Got format exception for zipfile: ' # Just skip if len(self.files) > 0: self.opennext() diff --git a/deluge/plugins/blocklist/blocklist/torrentblocklist.py b/deluge/plugins/blocklist/blocklist/torrentblocklist.py new file mode 100644 index 000000000..e6ca5a9c6 --- /dev/null +++ b/deluge/plugins/blocklist/blocklist/torrentblocklist.py @@ -0,0 +1,386 @@ +# +# blocklist/blocklist.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# Copyright (C) 2008 Mark Stahler ('kramed') + +# a snip or two used from johhnyg + +# +# 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 2 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. + +# TODO: +# - ZERO connections until after import +# - download timeouts / retries + +import urllib2, httplib, socket, os, datetime, sys +import deluge.common +import deluge.component # for libtorrent session reference to change connection number +import deluge.configmanager # used to retrieve max_global_connections +from deluge.log import LOG as log +#import ui # added by Mark for pausing torrents +from peerguardian import PGReader, PGException +from text import TextReader, GZMuleReader, PGZip + +BLOCKLIST_PREFS = { + "url": "http://www.bluetack.co.uk/config/pipfilter.dat.gz", + "load_on_start": False, + "check_after_days": 2, + "listtype": "gzmule", + "timeout": 180, + "try_times": 3 +} + +BACKUP_PREFS = { + "url": "http://www.bluetack.co.uk/config/pipfilter.dat.gz", + "listtype": "gzmule", +} + +FORMATS = { + 'gzmule': ["Emule IP list (GZip)", GZMuleReader, None], + 'spzip': ["SafePeer Text (Zipped)", PGZip, None], + 'pgtext': ["PeerGuardian Text (Uncompressed)", TextReader, None], + 'p2bgz': ["PeerGuardian P2B (GZip)", PGReader, None] +} + +class HTTPConnection(httplib.HTTPConnection): + """A customized HTTPConnection allowing a per-connection timeout, specified at construction.""" + + def __init__(self, host, port=None, strict=None, timeout=None): + httplib.HTTPConnection.__init__(self, host, port, strict) + self.timeout = timeout + + def connect(self): + """Override HTTPConnection.connect to connect to host/port specified in __init__.""" + + msg = "getaddrinfo returns an empty list" + for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM): + af, socktype, proto, canonname, sa = res + try: + self.sock = socket.socket(af, socktype, proto) + if self.timeout: + self.sock.settimeout(self.timeout) + self.sock.connect(sa) + except socket.error, msg: + if self.sock: + self.sock.close() + self.sock = None + continue + break + if not self.sock: + raise socket.error, msg + + +class HTTPHandler(urllib2.HTTPHandler): + """A customized HTTPHandler which times out connection after the duration specified at construction.""" + + def __init__(self, timeout=None): + urllib2.HTTPHandler.__init__(self) + self.timeout = timeout + + def http_open(self, req): + """Override http_open.""" + + def makeConnection(host, port=None, strict=None): + return HTTPConnection(host, port, strict, timeout = self.timeout) + + #print "HTTPHandler opening", req.get_full_url() + return self.do_open(makeConnection, req) + + +class TorrentBlockList: + def __init__(self, coreplugin): + self.plugin = coreplugin # reference from plugin core + log.info('Blocklist: TorrentBlockList instantiated') + self.config = deluge.configmanager.ConfigManager("blocklist.conf", BLOCKLIST_PREFS) + self.curr = 0 + self.load_options() + + # Make sure we have a current block list file locally + self.fetch = False + self.local_blocklist = deluge.configmanager.get_config_dir("blocklist.cache") + + # Check list for modifications from online version + self.check_update() + + if self.fetch == True: + self.download() + + log.debug('Blocklist: TorrentBlockList Constructor finished') + + + def load_options(self): + # Fill variables with settings from block list configuration file + self.url = self.config['url'] + self.listtype = self.config['listtype'] + self.check_after_days = self.config['check_after_days'] + self.load_on_start = self.config['load_on_start'] + self.timeout = self.config['timeout'] + self.try_times = self.config['try_times'] + + self.old_url = self.url + self.old_listtype = self.listtype + + socket.setdefaulttimeout(self.timeout) + + def set_options(self, options): + log.info('Blocklist: Options saved...') + self.config.set('url', options['url']) + self.config.set('check_after_days', options['check_after_days']) + self.config.set('load_on_start', options['load_on_start']) + self.config.set('listtype', options['listtype']) + self.config.set('timeout', options['timeout']) + self.config.set('try_times', options['try_times']) + # Save settings to disk + self.config.save() + # Load newly set options to core plugin + self.load_options() + + def check_update(self, force_check=False): + log.info('Blocklist: Checking for updates') + + try: + # Check current block lists time stamp and decide if it needs to be replaced + list_stats = os.stat(self.local_blocklist) + list_time = datetime.datetime.fromtimestamp(list_stats.st_mtime) + list_size = list_stats.st_size + current_time = datetime.datetime.today() + + except: + self.fetch = True + return + + # If local blocklist file exists but nothing is in it + if list_size == 0: + self.fetch = True + return + + if current_time >= (list_time + datetime.timedelta(self.check_after_days)): + check_newer = True + log.debug('Blocklist: List may need to be replaced') + else: + check_newer = False + + # If the program decides it is time to get a new list + if check_newer == True or force_check == True: + log.debug('Blocklist: Attempting check') + + j = 0 # counter for loop + + while j < self.try_times: + # Get current online block lists time stamp and compare it with current + try: + http_handler = HTTPHandler(timeout = self.timeout) + opener = urllib2.build_opener(http_handler) + request = urllib2.Request(self.url) + + try: + new_listinfo = opener.open(request) # Can Raise URLError + header = new_listinfo.info() + remote_size = int(header['content-length']) + remote_time = datetime.datetime.strptime(header['last-modified'],"%a, %d %b %Y %H:%M:%S GMT") + remote_type = header['content-type'] + + except URLError, e: + log.warning("Blocklist: Requesnt online blocklist info failed") + j += 1 + break + + except Exception, e: + log.warning(e) + # HANDLE EXCEPTOIN + j = self.try_times + break + + log.debug(self.listtype) + + # check expected list type + if self.listtype == "spzip": + list_type = "application/zip" + elif self.listtype == "gzmule" or self.listtype == "p2bgz": + list_type = "application/x-gzip" + else: + list_type = "text/html" + + # Print remote file information and local + log.debug('Blocklist: remote') + log.debug(remote_type) + log.debug(remote_time) + log.debug(remote_size) + log.debug('Blocklist: local') + log.debug(list_type) + log.debug(list_time) + log.debug(list_size) + + # Compare MIME types of local and remote list + if list_type == remote_type: + log.info('Blocklist: Remote and Local have the same list type') + # Compare last modified times and decide to download a new list or not + if list_time < remote_time or list_size != remote_size: + self.fetch = True + log.info('Blocklist: Local blocklist list is out of date') + + else: + self.fetch = False + log.info('Blocklist: Local block list is up to date') + + return + + j+=1 + log.debug('Blocklist: TRY AGAIN FOO') + + # Connection can't be made to check remote time stamps + except: # && urllib2.URLError + log.debug('Blocklist: Connection to remote server timed out') + self.fetch = False + j+=1 + + else: + log.info('Blocklist: Not enough time has passed to check for a new list') + return + + def download(self): + log.info('Blocklist: Beginning download') + + i = 0 + success = False + + while i < self.try_times or success == False: + # Download a new block list + try: + log.info('Blocklist: Downloading new list...') + http_handler = HTTPHandler(timeout = self.timeout) + opener = urllib2.build_opener(http_handler) + request = urllib2.Request(self.url) + new_list = opener.open(request) + + file = open(deluge.configmanager.get_config_dir("blocklist.cache"), 'w') + log.info('Blocklist: Writing blocklist to disk') + + # Write new blocklist to disk + while 1: + data = new_list.read() + if not len(data): + break + file.write(data) + file.close() + + except OSError, e: + log.debug('Blocklist: Unable to write blocklist file') + return + + except: + if i > self.try_times: + log.warning('Blocklist: All download attempts failed') + return + + else: + log.warning('Blocklist: Try list download again') + i += 1 + + # CHECKSUM + success = True + break + # end while loop + + log.info('Blocklist: List downloaded sucessfully') + # Download completed + + def import_list(self): + log.info('Blocklist: Importing list...') + # During import, disable remote connections by setting max to 0 + deluge.component.get("Core").session.set_max_connections(0) + + #TODO: Dont need try anymore + try: + self.plugin.reset_ip_filter() + self.curr = 0 + log.info('Blocklist: IP Filter reset') + except: + log.debug('Blocklist: Reset filter failed') + pass + + # Instantiate format class that will read the lists file format + try: + log.info('Blocklist: ' + str(self.listtype)) + read_list = FORMATS[self.listtype][1](self.local_blocklist) + + except: + log.warning('Blocklist: Error: Format read error') + self.reset_critical_settings() + + try: + ips = read_list.next() + + while ips: + self.plugin.block_ip_range(ips) + ips = read_list.next() + self.curr += 1 + # Progress measurement here + + log.info(self.curr) + + except IOError, e: + log.debug('Blocklist: Problem with list, re-download') + return + + # If experiencing an unrecoverable error, reset critical settings (url, listtype) + if self.curr == 0: + log.warning("Blocklist: Improper list read") + self.reset_critical_settings() + + else: # Sucessful import + deluge.component.get("Core").session.set_max_connections(deluge.configmanager.ConfigManager("core.conf")["max_connections_global"]) + log.info('Blocklist: Import completed sucessfully') + + def reset_critical_settings(self): + log.info('Blocklist: URL and List type reset') + reset_url = BACKUP_PREFS["url"] + reset_listtype = BACKUP_PREFS["listtype"] + + log.info(reset_url) + log.info(reset_listtype) + + self.config.set('url', reset_url) + self.config.set('listtype', reset_listtype) + self.config.save() + + self.load_options() + log.info(self.url) + log.info(self.listtype) + self.download() + self.import_list() + + def return_count(self): + return self.curr + + def get_config_value(self, key): # url, check_after_days, listtype + val = self.config[key] + log.debug('Blocklist: Get_config_val') + return val diff --git a/deluge/plugins/blocklist/blocklist/ui.py b/deluge/plugins/blocklist/blocklist/ui.py new file mode 100644 index 000000000..94b5f4b9f --- /dev/null +++ b/deluge/plugins/blocklist/blocklist/ui.py @@ -0,0 +1,53 @@ +# +# blocklist/ui.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# Copyright (C) 2008 Mark Stahler ('kramed') + +# +# 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 2 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 gettext +import locale +import pkg_resources +import deluge.component +from deluge.ui.client import aclient as client +from deluge.log import LOG as log + +class UI: + def __init__(self, plugin_api, plugin_name): + self.plugin = plugin_api + + def enable(self): + pass + + def disable(self): + pass + + \ No newline at end of file diff --git a/deluge/plugins/blocklist/blocklist/webui.py b/deluge/plugins/blocklist/blocklist/webui.py new file mode 100644 index 000000000..09c98779c --- /dev/null +++ b/deluge/plugins/blocklist/blocklist/webui.py @@ -0,0 +1,91 @@ +# +# blocklist/webui.py +# +# Copyright (C) 2008 Martijn Voncken + +# +# 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 2 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 os +from deluge.log import LOG as log +from deluge.ui.client import sclient +from deluge import component +import ui + +import deluge.ui.webui.lib.newforms_plus as forms + +config_page_manager = component.get("ConfigPageManager") + +FORMAT_LIST = [ + ('gzmule',_("Emule IP list (GZip)")), + ('spzip',_("SafePeer Text (Zipped)")), + ('pgtext',_("PeerGuardian Text (Uncompressed)")), + ('p2bgz',_("PeerGuardian P2B (GZip)")) +] + +class BlockListCfgForm(forms.Form): + """ + a config form based on django forms. + see webui.lib.newforms_plus, config_forms, etc. + """ + #meta: + title = _("BlockList") + + #load/save: + def initial_data(self): + return sclient.block_list_get_options() + + def save(self, data): + sclient.block_list_set_options(dict(data)) + + #input fields : + listtype = forms.ChoiceField(FORMAT_LIST) + url = forms.URLField(label=_("Url")) + check_after_days = forms.IntegerField(label=_("Check for a blocklist every (days)"), min_value=-1, max_value=14) + timeout = forms.IntegerField(label=_("Timeout (seconds)"), min_value=15, max_value=360) + try_times = forms.IntegerField(label=_("Times to attemptdownload of new list"), min_value=1, max_value=5) + load_on_start = forms.CheckBox(_('Import blocklist on daemon startup')) + +class WebUI(ui.UI): + def __init__(self, plugin_api, plugin_name): + log.debug("Calling UI init") + # Call UI constructor + ui.UI.__init__(self, plugin_api, plugin_name) + log.debug("Blocklist WebUI plugin initalized..") + + def enable(self): + config_page_manager.register('plugins','blocklist',BlockListCfgForm) + + def disable(self): + config_page_manager.unregister('blocklist') + + + + + diff --git a/deluge/plugins/blocklist/setup.py b/deluge/plugins/blocklist/setup.py new file mode 100644 index 000000000..c17541615 --- /dev/null +++ b/deluge/plugins/blocklist/setup.py @@ -0,0 +1,56 @@ +# setup.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# Copyright (C) 2008 Mark Stahler ('kramed') + +# +# 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 2, 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. + +""" +Download and import IP Blocklists +""" + +from setuptools import setup + +__author__ = "Mark Stahler" + +setup( + name="Block List", + version="1.0", + description=__doc__, + author=__author__, + packages=["blocklist"], + package_data = {"blocklist": ["data/*"]}, + entry_points=""" + [deluge.plugin.core] + Blocklist = blocklist:CorePlugin + [deluge.plugin.gtkui] + Blocklist = blocklist:GtkUIPlugin + [deluge.plugin.webui] + Blocklist = blocklist:WebUIPlugin + """ +) diff --git a/deluge/plugins/corepluginbase.py b/deluge/plugins/corepluginbase.py new file mode 100644 index 000000000..e6f393a17 --- /dev/null +++ b/deluge/plugins/corepluginbase.py @@ -0,0 +1,48 @@ +# +# core.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 + +class CorePluginBase: + def __init__(self, plugin_api, plugin_name): + self.plugin = plugin_api + # Register all export_* functions + for func in dir(self): + if func.startswith("export_"): + log.debug("Registering export function %s as %s", func, + plugin_name.lower() + "_" + func[7:]) + self.plugin.get_core().register_function( + getattr(self, "%s" % func), plugin_name.lower()\ + + "_" + func[7:]) + log.debug("CorePlugin initialized..") + diff --git a/deluge/plugins/init.py b/deluge/plugins/init.py new file mode 100644 index 000000000..1221b6b74 --- /dev/null +++ b/deluge/plugins/init.py @@ -0,0 +1,51 @@ +# +# init.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 + +class PluginBase: + def __init__(self): + self.plugin = None + + def enable(self): + try: + self.plugin.enable() + except Exception, e: + log.warning("Unable to enable plugin: %s", e) + + def disable(self): + try: + self.plugin.disable() + except Exception, e: + log.warning("Unable to disable plugin: %s", e) + diff --git a/deluge/plugins/label/label/__init__.py b/deluge/plugins/label/label/__init__.py new file mode 100644 index 000000000..921605c49 --- /dev/null +++ b/deluge/plugins/label/label/__init__.py @@ -0,0 +1,62 @@ +# +# __init__.py +# +# Copyright (C) 2008 Martijn Voncken +# +# 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 2 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.init import PluginBase + +class CorePlugin(PluginBase): + def __init__(self, plugin_api, plugin_name): + # Load the Core portion of the plugin + try: + from core import Core + self.plugin = Core(plugin_api, plugin_name) + except Exception, e: + log.debug("Did not load a Core plugin: %s", e) + +class WebUIPlugin(PluginBase): + def __init__(self, plugin_api, plugin_name): + try: + from webui import WebUI + self.plugin = WebUI(plugin_api, plugin_name) + except Exception, e: + log.debug("Did not load a WebUI plugin: %s", e) + +class GtkUIPlugin(PluginBase): + def __init__(self, plugin_api, plugin_name): + # Load the GtkUI portion of the plugin + try: + from gtkui import GtkUI + self.plugin = GtkUI(plugin_api, plugin_name) + except Exception, e: + log.debug("Did not load a GtkUI plugin: %s", e) + diff --git a/deluge/plugins/label/label/core.py b/deluge/plugins/label/label/core.py new file mode 100644 index 000000000..6fefb0231 --- /dev/null +++ b/deluge/plugins/label/label/core.py @@ -0,0 +1,380 @@ +# +# Copyright (C) 2008 Martijn Voncken +# +# 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 2 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. + +""" +torrent-label core plugin. +adds a status field for tracker. +""" + +from deluge.log import LOG as log +from deluge.plugins.corepluginbase import CorePluginBase +from deluge.configmanager import ConfigManager + +from urlparse import urlparse + +import traceback +import re + +RE_VALID = re.compile("[a-z0-9_-]*\Z") +RE_VALID = re.compile("[a-z0-9_-]*\Z") + +KNOWN_STATES = ['Downloading','Seeding','Paused','Checking','Allocating','Queued','Error'] +STATE = "state" +TRACKER = "tracker" +KEYWORD = "keyword" +LABEL = "label" +CONFIG_DEFAULTS = { + "torrent_labels":{}, #torrent_id:label_id + "labels":{}, #label_id:{name:value} + "hide_zero_hits":False, + "gtk_alfa":False +} +OPTIONS_KEYS = ["max_download_speed", "max_upload_speed", + "max_connections", "max_upload_slots", "prioritize_first_last"] +NO_LABEL = "No Label" + + +def CheckInput(cond, message): + if not cond: + raise Exception(message) + + +class Core(CorePluginBase): + def enable(self): + log.info("*** Start Label plugin ***") + + self.plugin.register_status_field("tracker_host", self._status_get_tracker) + self.plugin.register_status_field("label", self._status_get_label) + + #__init__ + core = self.plugin.get_core() + self.config = ConfigManager("label.conf") + self.core_cfg = ConfigManager("core.conf") + self.set_config_defaults() + + #reduce typing, assigning some values to self... + self.torrents = core.torrents.torrents + self.labels = self.config.get("labels") + self.torrent_labels = self.config.get("torrent_labels") + + log.debug("Label plugin enabled..") + + def clean_config(self): + "remove invalid data from config-file" + for torrent_id, label_id in list(self.torrent_labels.iteritems()): + if (not label_id in self.labels) or (not torrent_id in self.torrents): + log.debug("label: rm %s:%s" % (torrent_id,label_id)) + del self.torrent_labels[torrent_id] + + def save_config(self): + self.clean_config() + self.config.save() + + def set_config_defaults(self): + changed = False + for key, value in CONFIG_DEFAULTS.iteritems(): + if not key in self.config.config: + self.config.config[key] = value + changed = True + if changed: + pass + #self.config.save() + log.debug("label_config=%s" % self.config.config) + + def disable(self): + # De-register the label field + self.plugin.deregister_status_field("tracker_host") + self.plugin.deregister_status_field("label") + + def update(self): + pass + + ## Utils ## + def get_tracker(self, torrent): + """ + returns 1st tracker hostname + save space: reduced to *.com without any subdomain dots before + TODO: CLEANUP + """ + log.debug(torrent) + log.debug(torrent.trackers) + if not torrent.trackers: + return 'tracker-less' + url = urlparse(torrent.trackers[0]['url']) + if hasattr(url,'hostname'): + host = (url.hostname or 'unknown?') + parts = host.split(".") + if len(parts) > 2: + host = ".".join(parts[-2:]) + return host + return 'No-tracker?' + + ## Filters ## + def filter_state(self, torrents, value): + "in/out: a list of torrent objects." + log.debug("filter-state:%s" % value) + for t in torrents: + log.debug("s=%s" % t.state) + return [t for t in torrents if t.state == value] + + def filter_tracker(self, torrents, value): + "in/out: a list of torrent objects." + return [t for t in torrents if self.get_tracker(t) == value] + + def filter_label(self, torrents, value): + "in/out: a list of torrent objects." + if value == NO_LABEL: + value = None + log.debug("NO_LABEL") + return [t for t in torrents if self.torrent_labels.get(t.torrent_id) == value] + + def filter_keyword(self, torrents, value): + value = value.lower().strip() + "in/out: a list of torrent objects." + return [t for t in torrents if value in t.filename.lower()] + + ## Items ## + def get_state_filter_items(self): + states = dict([(state, 0) for state in KNOWN_STATES]) + state_order = list(KNOWN_STATES) + #state-simple: + for t in self.torrents.values(): + if not t.state in state_order: + state_order.append(t.state) + states[t.state] = 0 + states[t.state] +=1 + #specialized-state: + #todo: traffic. + + log.debug("hide-z:%s" % self.config["hide_zero_hits"]) + if self.config["hide_zero_hits"]: + for state in set(KNOWN_STATES): + log.debug(states.keys()) + if states[state] == 0 : + #del states[state] + state_order.remove(state) + + #return the filters sorted by STATES + add unknown states. + return ([("All",len(self.torrents))] + + [(state, states[state]) for state in state_order] + ) + + def get_tracker_filter_items(self): + #trackers: + trackers = {} + for t in self.torrents.values(): + tracker = self.get_tracker(t) + if not tracker in trackers: + trackers[tracker] = 0 + trackers[tracker] +=1 + + return [(tracker , trackers[tracker]) for tracker in sorted(trackers.keys())] + + def get_label_filter_items(self): + no_label = 0 + labels = dict([(label_id, 0) for label_id in self.labels]) + for torrent_id in self.torrents: + label_id = self.torrent_labels.get(torrent_id) + if label_id: + labels[label_id] +=1 + else: + no_label +=1 + + if self.config["hide_zero_hits"]: + for label , count in list(labels.iteritems()): + if count == 0: + del labels[label] + + return [(NO_LABEL, no_label)] + [(label_id, labels[label_id]) for label_id in sorted(labels.keys())] + + ## Public ## + def export_filter_items(self): + """ + returns : + { + "CATEGORY" : [("filter_value",count), ...] , ... + } + -- + category's : ["state","tracker","label"] + """ + result = {} + + result[STATE] = self.get_state_filter_items() + result[TRACKER] = self.get_tracker_filter_items() + result[LABEL] = self.get_label_filter_items() + + return result + + def export_get_labels(self): + return sorted(self.labels.keys()) + + def export_get_filtered_ids(self, filter_dict): + """ + input : {"filter_cat":"filter_value",..} + returns : a list of torrent_id's + """ + torrents = self.torrents.values() + if KEYWORD in filter_dict: + torrents = self.filter_keyword(torrents, filter_dict[KEYWORD]) + + if STATE in filter_dict and filter_dict[STATE] <> "": + torrents = self.filter_state(torrents, filter_dict[STATE]) + + if TRACKER in filter_dict: + torrents = self.filter_tracker(torrents, filter_dict[TRACKER]) + + if LABEL in filter_dict: + torrents = self.filter_label(torrents, filter_dict[LABEL]) + return [t.torrent_id for t in torrents] + + + #Labels: + def export_add(self, label_id): + """add a label + see label_set_options for more options. + """ + label_id = label_id.lower() + CheckInput(RE_VALID.match(label_id) , _("Invalid label, valid characters:[a-z0-9_-]")) + CheckInput(label_id, _("Empty Label")) + CheckInput(not (label_id in self.labels) , _("Unknown Label")) + + + #default to current global per-torrent settings. + self.labels[label_id] = { + "max_download_speed":self.core_cfg.config["max_download_speed_per_torrent"], + "max_upload_speed":self.core_cfg.config["max_upload_speed_per_torrent"], + "max_connections":self.core_cfg.config["max_connections_per_torrent"], + "max_upload_slots":self.core_cfg.config["max_upload_slots_per_torrent"], + "prioritize_first_last":self.core_cfg.config["prioritize_first_last_pieces"] + } + + def export_remove(self, label_id): + "remove a label" + CheckInput(label_id in self.labels, _("Unknown Label")) + del self.labels[label_id] + self.clean_config() + self.config.save() + + def export_set_options(self, label_id, options_dict , apply = False): + """update the label options + + options_dict : + {"max_download_speed":float(), + "max_upload_speed":float(), + "max_connections":int(), + "max_upload_slots":int(), + "prioritize_first_last":bool(), + } + + apply : applies download-options to all torrents currently labelled by label_id + """ + CheckInput(not (label_id in self.labels) , _("Unknown Label")) + for key in options_dict.keys(): + if not key in OPTIONS_KEYS: + raise Exception("label: Invalid options_dict key:%s" % key) + + self.labels[label_id].update(options_dict) + + options = self.labels[label_id] + if apply: + for torrent_id,label in self.torrent_labels.iteritems(): + if label_id == label: + torrent = self.torrents[torrent_id] + torrent.set_max_download_speed(options["max_download_speed"]) + torrent.set_max_upload_speed(options["max_upload_speed"]) + torrent.set_max_connections(options["max_connections"]) + torrent.set_max_upload_slots(options["max_upload_slots"]) + torrent.set_prioritize_first_last(options["prioritize_first_last"]) + + self.config.save() + + def export_get_options(self, label_id): + """returns the label options""" + return self.labels[label_id] + + def export_set_torrent(self, torrent_id , label_id): + """ + assign a label to a torrent + removes a label if the label_id parameter is empty. + """ + if label_id == NO_LABEL: + label_id = None + + CheckInput((not label_id) or (label_id in self.labels) , _("Unknown Label")) + CheckInput(torrent_id in self.torrents , _("Unknown Torrent")) + + if not label_id: + if torrent_id in self.torrent_labels: + del self.torrent_labels[torrent_id] + self.clean_config() + else: + self.torrent_labels[torrent_id] = label_id + #set speeds, etc: + options = self.labels[label_id] + torrent = self.torrents[torrent_id] + torrent.set_max_download_speed(options["max_download_speed"]) + torrent.set_max_upload_speed(options["max_upload_speed"]) + torrent.set_max_connections(options["max_connections"]) + torrent.set_max_upload_slots(options["max_upload_slots"]) + torrent.set_prioritize_first_last(options["prioritize_first_last"]) + + self.config.save() + + + def export_get_global_options(self): + "see : label_set_global_options" + return { + "hide_zero_hits":self.config.get("hide_zero_hits"), + "gtk_alfa":self.config.get("gtk_alfa") + } + + def export_set_global_options(self, options): + """global_options: + { + "hide_zero":bool() #label_filter_items only returns items with more than 0 hits. + } + """ + for key in ["hide_zero_hits", "gtk_alfa"]: + if options.has_key(key): + self.config.set(key, options[key]) + self.config.save() + + + ## Status fields ## + def _status_get_tracker(self, torrent_id): + return self.get_tracker(self.torrents[torrent_id]) + + def _status_get_label(self, torrent_id): + return self.torrent_labels.get(torrent_id) or "" + +if __name__ == "__main__": + import test + diff --git a/deluge/plugins/label/label/gtkui.py b/deluge/plugins/label/label/gtkui.py new file mode 100644 index 000000000..480183dd1 --- /dev/null +++ b/deluge/plugins/label/label/gtkui.py @@ -0,0 +1,357 @@ +# +# blocklist/gtkui.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# Copyright (C) 2008 Mark Stahler ('kramed') +# +# 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 2 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 os +import pkg_resources # access plugin egg +from deluge.log import LOG as log +from deluge import component # for systray +import ui +import gtk, gobject +from deluge.ui.client import aclient + +from deluge.configmanager import ConfigManager +config = ConfigManager("label.conf") +GTK_ALFA = config.get("gtk_alfa") +NO_LABEL = "No Label" + + +def cell_data_label(column, cell, model, row, data): + cell.set_property('text', str(model.get_value(row, data))) + +def cell_data_tracker_host(column, cell, model, row, data): + cell.set_property('text', str(model.get_value(row, data))) + +class GtkUI(ui.UI): + def __init__(self, plugin_api, plugin_name): + log.debug("Calling UI init") + # Call UI constructor + ui.UI.__init__(self, plugin_api, plugin_name) + log.debug("Label GtkUI plugin initalized..") + + def enable(self): + self.plugin.register_hook("on_apply_prefs", self.apply_prefs) + self.load_interface() + + def disable(self): + #deluge.component.get("StatusBar").remove_item(self.blocklist_status) + self.plugin.deregister_hook("on_apply_prefs", self.apply_prefs) + self.plugin.remove_preferences_page("Label") + + def get_pixmap(self, fname): + """Returns a pixmap file included with plugin""" + return pkg_resources.resource_filename("blocklist", os.path.join("data", fname)) + + def unload_interface(self): + self.plugin.remove_preferences_page("Label") + + + def load_interface(self): + if not GTK_ALFA: + self.plugin.add_preferences_page("Label", gtk.Label( + "Sorry, the Gtk UI for the Label-plugin is still in development.")) + return + + log.debug("add items to torrentview-popup menu.") + + torrentmenu = component.get("MenuBar").torrentmenu + + self.label_menu = LabelMenu() + torrentmenu.append(self.label_menu) + self.label_menu.show_all() + + log.debug("add columns") + + component.get("TorrentView").add_func_column(_("Label"), + cell_data_label, + [str], + status_field=["label"]) + + component.get("TorrentView").add_func_column(_("Tracker"), + cell_data_tracker_host, + [str], + status_field=["tracker_host"]) + + component.get("TorrentView").create_model_filter() #todo:improve. + #TODO! + log.debug("Beginning gtk pane initialization") + self.config_frame = LabelConfigFrame() + + self.blocklist_pref_page = gtk.VBox() + self.blocklist_pref_page.set_spacing(6) + + self.blocklist_pref_page.pack_start(self.config_frame,True,True) + + # Add preferences page to preferences page + log.debug('Adding Label Preferences page') + self.plugin.add_preferences_page("Label", self.blocklist_pref_page) + + # Load settings from config and fill widgets with settings + self.fetch_prefs() + #log.debug('Finished loading Label preferences') + + + def fetch_prefs(self): # Fetch settings dictionary from plugin core and pass it to GTK ui settings + log.info('LABEL: Fetching and loading Preferences via GTK ui') + #aclient.block_list_get_options(self.callback_load_prefs) + self.config_frame.load_settings() + + def apply_prefs(self): + log.info('Blocklist: Preferences saved via Gtk ui') + """settings_dict = { + "url": self.url.get_text(), + "listtype": self.get_ltype(), + "check_after_days": self.check_after_days.get_value_as_int(), + "load_on_start":self.load_on_start.get_active(), + "try_times": self.try_times.get_value_as_int(), + "timeout": self.timeout.get_value_as_int() + } + aclient.block_list_set_options(None, settings_dict) + # Needs to go in another thread or wait until window is closed + #gobject.idle_add(self.call_critical_setting) + """ + + + # GTK Gui Callback functions + def callback_load_prefs(self, dict): + self.config_frame.load_settings() + log.info('Blocklist: Callback Load Prefs GTK ui') + """self.settings_url(dict['url']) + self.settings_listtype(dict['listtype']) + self.settings_load(dict['load_on_start']) + self.settings_check_after_days(dict['check_after_days']) + self.settings_timeout(dict['timeout']) + self.settings_try_times(dict['try_times']) + """ + +def cb_none(args): + "hack for empty callbacks." + pass + +""" +class LabelList(gtk.TreeView): + "a simple listbox is way too hard in gtk :(." + def __init__(self): + pass +""" + +class LabelMenu(gtk.MenuItem): + def __init__(self): + gtk.MenuItem.__init__(self, "Label") + self.show_all() + + #attach.. + torrentmenu = component.get("MenuBar").torrentmenu + torrentmenu.connect("show", self.on_show, None) + + aclient.connect_on_new_core(self._on_new_core) + + def _on_new_core(self, data): + self.on_show() + + def get_torrent_ids(self): + return component.get("TorrentView").get_selected_torrents() + + + def on_show(self, widget=None, data=None): + log.debug("label-on-show") + aclient.label_get_labels(self.cb_labels) + aclient.force_call(block=True) + + def cb_labels(self , labels): + log.debug("cb_labels-start") + self.sub_menu = gtk.Menu() + for label in [NO_LABEL] + labels: + item = gtk.MenuItem(label) + item.connect("activate", self.on_select_label, label) + self.sub_menu.append(item) + self.set_submenu(self.sub_menu) + self.show_all() + log.debug("cb_labels-end") + + def on_select_label(self, widget=None, label_id = None): + log.debug("select label:%s,%s" % (label_id ,self.get_torrent_ids()) ) + for torrent_id in self.get_torrent_ids(): + aclient.label_set_torrent(cb_none, torrent_id, label_id) + #aclient.force_call(block=True) + +class LabelConfigFrame(gtk.Frame): + def __init__(self): + gtk.Frame.__init__(self) + self.build_label_view() + self.build_label_options() + self.build_ui() + self.labels = [] + aclient.connect_on_new_core(self._on_new_core) + + def _on_new_core(self, data): + log.debug("NEW CORE") + self.load_settings() + + def load_settings(self ,widget=None ,data=None): + aclient.label_get_labels(self.cb_update_labels) + + def cb_update_labels(self, labels): + self.labels = labels + self.label_store.clear() + for label in labels: + self.label_store.append([label]) + + def on_add(self, widget, data=None): + label = self.txt_add.get_text() + self.txt_add.set_text("") + if label in self.labels: + return + aclient.label_add(cb_none, label) + aclient.label_get_labels(self.cb_update_labels) + self.select_label(label) + + #aclient.force_call(block=True) + + def on_remove(self, widget, data=None): + label = self.get_selected_label() + aclient.label_remove(cb_none, label) + aclient.label_get_labels(self.cb_update_labels) + self.select_label(0) + + def get_selected_label(self): + model , iter = self.label_view.get_selection().get_selected() + return self.label_store.get_value(iter,0) + + def select_label(self, label): + aclient.force_call(block=True) #sync.. + if label: + it = self.label_store.iter_nth_child(None,self.labels.index(label)) + else: + it = self.label_store.iter_nth_child(None,0) + self.label_view.get_selection().select_iter(it) + + def build_label_view(self): + "gtk should have a simple listbox widget..." + self.label_store = gtk.ListStore(str) + + column = gtk.TreeViewColumn(_("Label")) + renderer = gtk.CellRendererText() + column.pack_start(renderer) + column.set_attributes(renderer, text = 0) + + self.label_view = gtk.TreeView(self.label_store) + self.label_view.append_column(column) + self.label_view.set_headers_visible(False) + + #self.label_scroll = gtk.ScrolledWindow() + #self.label_scroll.add_with_viewport(self.label_view) + + + def build_label_options(self): + self.label_options = gtk.Label("Per label options") + + def build_ui(self): + #vbox + #general + #[x] stuff + #labels: + #hpaned : left-right + #right: listbox with labels + #left: label-options + #--- + #label-add + #-- + + label = gtk.Label() + label.set_markup('' + _('General') + '') + + + self.set_shadow_type(gtk.SHADOW_NONE) + self.set_label_widget(label) + + self.btn_load = gtk.Button("Load Settings") + self.btn_load.connect("clicked", self.load_settings, None) + + self.btn_remove = gtk.Button("Remove") + self.btn_remove.connect("clicked", self.on_remove, None) + + vb = gtk.VBox() + self.add(vb) + vb.add(self.btn_load) + vb.add(gtk.Label("Label is in developent, you're testing pre-alfa!!!")) + + + self.hide_zero_hits = gtk.CheckButton(_('Hide Zero Hits')) + vb.add(self.hide_zero_hits) + + label = gtk.Label() + label.set_markup('' + _('Labels') + '') + vb.add(label) + + hp = gtk.HPaned() + hp.add1(self.label_view) + + + hp.add2(self.label_options) + + hp.set_position(100) + + hp.set_size_request(400, 200) #bug.. + + + hbAdd = gtk.HBox() + hbAdd.add(gtk.Label("Label:")) + self.txt_add = gtk.Entry() + hbAdd.add(self.txt_add) + btn_add = gtk.Button("Add") + hbAdd.add(btn_add) + btn_add.connect("clicked", self.on_add, None) + + vb.pack_end(hbAdd) + + label = gtk.Label() + label.set_markup('' + _('Add') + '') + + + + vb.pack_end(label) + + vb.pack_end(self.btn_remove, True , True) + + vb.pack_end(hp,True , True) + + + + + + + + + + diff --git a/deluge/plugins/label/label/template/part_label_filters.html b/deluge/plugins/label/label/template/part_label_filters.html new file mode 100644 index 000000000..62272ea3b --- /dev/null +++ b/deluge/plugins/label/label/template/part_label_filters.html @@ -0,0 +1,53 @@ +$def with (filter_items) + +
+ + + +
+
+
$_('Keyword')
+ + +$if get('filter_cat') == "keyword": + $if get('filter_value'): + $_('Clear') + +

+ + +$for cat in ["state", "tracker", "label"]: +
$cat
+ +
+
+ + + + diff --git a/deluge/plugins/label/label/template/torrent_label.html b/deluge/plugins/label/label/template/torrent_label.html new file mode 100644 index 000000000..f17404c2f --- /dev/null +++ b/deluge/plugins/label/label/template/torrent_label.html @@ -0,0 +1,29 @@ +$def with (torrent_ids, torrent_list, labels) +$:render.header(_("Label torrent")) +
+
+
+ +

$_("Label torrent")

+
    +$for torrent in torrent_list: +
  • $torrent.name ($torrent.label)
  • +
+ +
+ + +
+
+ + +
+
+
+
+$:render.footer() \ No newline at end of file diff --git a/deluge/plugins/label/label/test.py b/deluge/plugins/label/label/test.py new file mode 100644 index 000000000..a112d3b53 --- /dev/null +++ b/deluge/plugins/label/label/test.py @@ -0,0 +1,79 @@ +from deluge.ui.client import sclient + +sclient.set_core_uri() + +print sclient.get_enabled_plugins() + +#enable plugin. +if not "label" in sclient.get_enabled_plugins(): + sclient.enable_plugin("label") + +#test filter items. +print "# label_filter_items()" +for cat,filters in sclient.label_filter_items(): + print "-- %s --" % cat + for filter in filters: + print " * %s (%s)" % (filter[0],filter[1]) + +# test filtering +print "#len(sclient.label_get_filtered_ids({'tracker':'tracker.aelitis.com'} ))" +print len(sclient.label_get_filtered_ids({'tracker':'tracker.aelitis.com'} )) + +print "#len(sclient.label_get_filtered_ids({'state':'Paused'} ))" +print len(sclient.label_get_filtered_ids({'state':'Paused'} )) + + +print "#len(sclient.label_get_filtered_ids({'keyword':'az'} ))" +print len(sclient.label_get_filtered_ids({'keyword':'az'} )) + + +print "#len(sclient.label_get_filtered_ids({'state':'Paused','tracker':'tracker.aelitis.com'} ))" +print len(sclient.label_get_filtered_ids({'state':'Paused','tracker':'tracker.aelitis.com'} )) + +print "#test status-fields:" +ids = sclient.get_session_state() + +torrents = sclient.get_torrents_status(ids,['name', 'tracker_host', 'label']) + +for id,torrent in torrents.iteritems(): + print id, torrent + +#test labels. +print "#init labels" +try: + sclient.label_remove("test") +except: + pass +id = sclient.get_session_state()[0] + +print "#add" +sclient.label_add("test") +print "#set" +sclient.label_set_torrent(id,"test") + +print "#len(sclient.label_get_filtered_ids({'label':'test'} ))" +print len(sclient.label_get_filtered_ids({'label':'test'} )) + +#test filter items. +print "# label_filter_items()" +for cat,filters in sclient.label_filter_items(): + if cat == "label": + print "-- %s --" % cat + for filter in filters: + print " * %s (%s)" % (filter[0],filter[1]) + + +print "#set options" +sclient.label_set_options("test",{"max_download_speed":999}, True) +print sclient.get_torrent_status(id, ["max_download_speed"]) , "999" +sclient.label_set_options("test",{"max_download_speed":9}, True) +print sclient.get_torrent_status(id, ["max_download_speed"]) , "9" +sclient.label_set_options("test",{"max_download_speed":888}, False) +print sclient.get_torrent_status(id, ["max_download_speed"]) , "9 (888)" + +print sclient.get_torrent_status(id,['name', 'tracker_host', 'label']) + + + + + diff --git a/deluge/plugins/label/label/ui.py b/deluge/plugins/label/label/ui.py new file mode 100644 index 000000000..94b5f4b9f --- /dev/null +++ b/deluge/plugins/label/label/ui.py @@ -0,0 +1,53 @@ +# +# blocklist/ui.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# Copyright (C) 2008 Mark Stahler ('kramed') + +# +# 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 2 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 gettext +import locale +import pkg_resources +import deluge.component +from deluge.ui.client import aclient as client +from deluge.log import LOG as log + +class UI: + def __init__(self, plugin_api, plugin_name): + self.plugin = plugin_api + + def enable(self): + pass + + def disable(self): + pass + + \ No newline at end of file diff --git a/deluge/plugins/label/label/webui.py b/deluge/plugins/label/label/webui.py new file mode 100644 index 000000000..5bdc03f75 --- /dev/null +++ b/deluge/plugins/label/label/webui.py @@ -0,0 +1,63 @@ +# +# blocklist/webui.py +# +# Copyright (C) 2008 Martijn Voncken + +# +# 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 2 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 os +from deluge.log import LOG as log +from deluge.ui.client import sclient +from deluge import component +import ui + +import webui_config +import webui_pages + +class WebUI(ui.UI): + def __init__(self, plugin_api, plugin_name): + log.debug("Calling UI init") + # Call UI constructor + ui.UI.__init__(self, plugin_api, plugin_name) + log.debug("Label WebUI plugin initalized..") + + def enable(self): + webui_pages.register() + webui_config.register() + + def disable(self): + webui_pages.unregister() + webui_config.unregister() + + + + + + diff --git a/deluge/plugins/label/label/webui_config.py b/deluge/plugins/label/label/webui_config.py new file mode 100644 index 000000000..c11c85650 --- /dev/null +++ b/deluge/plugins/label/label/webui_config.py @@ -0,0 +1,149 @@ +# +# Copyright (C) 2008 Martijn Voncken +# +# 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 2 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 os +from deluge.log import LOG as log +from deluge.ui.client import sclient +from deluge import component + +api = component.get("WebPluginApi") +forms = api.forms + +class LabelUpdateCfgForm(forms.Form): + """ + a config form based on django forms. + see webui.lib.newforms_plus, config_forms, etc. + """ + #meta: + title = _("Labels") + + def get_selected(self): + selected = api.web.input(label = None).label + labels = sclient.label_get_labels() + if not selected: + if labels: + selected = labels[0] + return selected + + def pre_html(self): + selected = self.get_selected() + html = _("Select Label") + ":" + for label in sclient.label_get_labels(): + html += """ + %(label)s  """ % {"label":label} + html += "

%s

" % selected + return html + #load/save: + def initial_data(self): + label_id = self.get_selected() + return sclient.label_get_options(label_id) + + def save(self, data): + label_id = self.get_selected() + apply = data.apply + delete = data.delete + + if delete: + sclient.label_remove(label_id) + raise Exception("DELETED") + else: + del data["apply"] + del data["delete"] + sclient.label_set_options(label_id, dict(data), apply) + + #input fields : + max_connections = forms.DelugeInt(_("Maximum Connections")) + max_download_speed = forms.DelugeFloat(_("Maximum Download Speed (Kib/s)")) + max_upload_speed = forms.DelugeFloat(_("Maximum Upload Speed (Kib/s)")) + max_upload_slots = forms.DelugeInt(_("Maximum Upload Slots")) + + apply = forms.CheckBox(_("Apply")) + delete = forms.CheckBox(_("Delete")) + + + +class LabelAddCfgForm(forms.Form): + """ + a config form based on django forms. + see webui.lib.newforms_plus, config_forms, etc. + """ + #meta: + title = _("Add Label") + + #load/save: + def initial_data(self): + return { } + + def save(self, data): + sclient.label_add(data.label) + + label = forms.CharField(_("Label")) + +class LabelCfgForm(forms.Form): + """ + global settings. + """ + #meta: + title = _("General") + + #load/save: + def initial_data(self): + return sclient.label_get_global_options() + + def save(self, data): + return sclient.label_set_global_options(dict(data)) + + hide_zero_hits = forms.CheckBox(_("Hide filter items with 0 hits")) + #gtk_alfa = forms.CheckBox(_("gtk_alfa")) + + + + +def register(): + api.config_page_manager.register('label','label_general',LabelCfgForm) + api.config_page_manager.register('label','label_update',LabelUpdateCfgForm) + api.config_page_manager.register('label','label_add',LabelAddCfgForm) + +def unregister(): + api.config_page_manager.unregister('label_general') + api.config_page_manager.unregister('label_update') + api.config_page_manager.unregister('label_add') + + + + + + + + + + + diff --git a/deluge/plugins/label/label/webui_pages.py b/deluge/plugins/label/label/webui_pages.py new file mode 100644 index 000000000..b644a793f --- /dev/null +++ b/deluge/plugins/label/label/webui_pages.py @@ -0,0 +1,79 @@ +# +# +# Copyright (C) 2008 Martijn Voncken +# +# 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 2 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 os +from deluge.log import LOG as log +from deluge.ui.client import sclient +from deluge import component + +api = component.get("WebPluginApi") + +template_dir = os.path.join(os.path.dirname(__file__),"template") + +class torrent_label: + @api.deco.deluge_page + @api.deco.torrent_list + def GET(self, torrent_list): + torrent_str = ",".join([t.id for t in torrent_list]) + labels = sclient.label_get_labels() + return api.render.torrent_label(torrent_str , torrent_list , labels) + + @api.deco.check_session + @api.deco.torrent_ids + def POST(self, torrent_ids): + label =api.web.input(label = None).label + for id in torrent_ids: + sclient.label_set_torrent(id , label) + api.utils.do_redirect() + + +def register(): + api.render.register_template_path(template_dir) + api.page_manager.register_page('/torrent/label/(.*)', torrent_label) + api.menu_manager.register_toolbar_item("label",_("Label"), "label.png" ,2, + "GET","/torrent/label/", True) + +def unregister(): + api.render.unregister_template_path(template_dir) + api.page_manager.unregister_page('/torrent/label/(.*)') + api.menu_manager.unregister_toolbar_item("label") + + + + + + + + + + + diff --git a/deluge/plugins/label/setup.py b/deluge/plugins/label/setup.py new file mode 100644 index 000000000..959b5c9cd --- /dev/null +++ b/deluge/plugins/label/setup.py @@ -0,0 +1,60 @@ +# setup.py +# +# Copyright (C) 2008 Martijn Voncken +# +# 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 2, 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. + +""" +Label plugin. + +Offers filters on state,tracker and keyword. +adds a tracker column. + +future: Real labels. + +""" + +from setuptools import setup + +__author__ = "Martijn Voncken " + +setup( + name="Label", + version="0.1", + description=__doc__, + author=__author__, + packages=["label"], + package_data = {"label": ["template/*"]}, + entry_points=""" + [deluge.plugin.core] + Label = label:CorePlugin + [deluge.plugin.webui] + Label = label:WebUIPlugin + [deluge.plugin.gtkui] + Label = label:GtkUIPlugin + """ +) diff --git a/deluge/plugins/testp/setup.py b/deluge/plugins/testp/setup.py new file mode 100644 index 000000000..2d972c15d --- /dev/null +++ b/deluge/plugins/testp/setup.py @@ -0,0 +1,52 @@ +# setup.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2, 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. + +""" +Test plugin +""" + +from setuptools import setup + +__author__ = "Andrew Resch" + +setup( + name="Test Plugin", + version="1.0", + description=__doc__, + author=__author__, + packages=["testp"], + package_data = {"testp": ["glade/*.glade"]}, + entry_points=""" + [deluge.plugin.core] + Testp = testp:CorePlugin + [deluge.plugin.gtkui] + Testp = testp:GtkUIPlugin + """ +) diff --git a/deluge/plugins/testp/testp/__init__.py b/deluge/plugins/testp/testp/__init__.py new file mode 100644 index 000000000..37219e170 --- /dev/null +++ b/deluge/plugins/testp/testp/__init__.py @@ -0,0 +1,54 @@ +# +# __init__.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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.init import PluginBase + +class CorePlugin(PluginBase): + def __init__(self, plugin_api, plugin_name): + # Load the Core portion of the plugin + try: + from core import Core + self.plugin = Core(plugin_api, plugin_name) + except Exception, e: + log.debug("Did not load a Core plugin: %s", e) + +class GtkUIPlugin(PluginBase): + def __init__(self, plugin_api, plugin_name): + # Load the GtkUI portion of the plugin + try: + from gtkui import GtkUI + self.plugin = GtkUI(plugin_api, plugin_name) + except Exception, e: + log.debug("Did not load a GtkUI plugin: %s", e) diff --git a/deluge/plugins/testp/testp/core.py b/deluge/plugins/testp/testp/core.py new file mode 100644 index 000000000..9660ccd91 --- /dev/null +++ b/deluge/plugins/testp/testp/core.py @@ -0,0 +1,43 @@ +# +# core.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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.corepluginbase import CorePluginBase + +class Core(CorePluginBase): + def enable(self): + pass + + def disable(self): + pass + diff --git a/deluge/plugins/testp/testp/gtkui.py b/deluge/plugins/testp/testp/gtkui.py new file mode 100644 index 000000000..da6d4582c --- /dev/null +++ b/deluge/plugins/testp/testp/gtkui.py @@ -0,0 +1,51 @@ +# +# gtkui.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 +import ui + +class GtkUI(ui.UI): + def __init__(self, plugin_api, plugin_name): + log.debug("Calling UI init") + # Call UI constructor + ui.UI.__init__(self, plugin_api, plugin_name) + log.debug("test plugin initialized..") + + def enable(self): + self.plugin.register_hook("on_apply_prefs", self.apply_prefs) + + def disable(self): + self.plugin.deregister_hook("on_apply_prefs", self.apply_prefs) + + def apply_prefs(self): + log.debug("applying prefs in test plugin!!") diff --git a/deluge/plugins/testp/testp/ui.py b/deluge/plugins/testp/testp/ui.py new file mode 100644 index 000000000..92ea56ecf --- /dev/null +++ b/deluge/plugins/testp/testp/ui.py @@ -0,0 +1,44 @@ +# +# ui.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 + +class UI: + def __init__(self, plugin_api, plugin_name): + self.plugin = plugin_api + + def enable(self): + pass + + def disable(self): + pass diff --git a/deluge/scripts/state_upgrade.py b/deluge/scripts/state_upgrade.py new file mode 100644 index 000000000..8aab37f9f --- /dev/null +++ b/deluge/scripts/state_upgrade.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) Martijn Voncken 2008 +# +# 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 2, 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. + +import sys, pickle , shutil , os +from deluge.ui.client import sclient + +options = { + "new_torrents_dir" :"~/torrents06", + "state05":"~/.config/deluge/persistent.state", + "all_paused":True +} + +#start : http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/286203 +def makeFakeClass(module, name): + class FakeThing(object): + pass + FakeThing.__name__ = name + FakeThing.__module__ = '(fake)' + module + return FakeThing + +class PickleUpgrader(pickle.Unpickler): + def find_class(self, module, cname): + # Pickle tries to load a couple things like copy_reg and + # __builtin__.object even though a pickle file doesn't + # explicitly reference them (afaict): allow them to be loaded + # normally. + if module in ('copy_reg', '__builtin__'): + thing = pickle.Unpickler.find_class(self, module, cname) + return thing + return makeFakeClass(module, cname) +# end: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/286203 + +def load_05(state_05_file, new_torrent_dir,all_paused): + state5 = PickleUpgrader(open(state_05_file)).load() + for torrent in state5.torrents: + #print [x for x in dir(torrent) if not x.startswith("_")] + print "file:%s, save_dir:%s, compact:%s, paused:%s " % (torrent.filename,torrent.save_dir,torrent.compact,torrent.user_paused) + + new_file = os.path.join(new_torrent_dir,os.path.basename(torrent.filename)) + print "copy" ,torrent.filename , new_file + shutil.copyfile(torrent.filename , new_file) + + sclient.add_torrent_file([torrent.filename],[{ + "add_paused" : (all_paused or torrent.user_paused), + "compact_allocation":torrent.compact, + "download_location":torrent.save_dir + }]) + +if __name__ == "__main__": + sclient.set_core_uri() + new_torrents_dir = os.path.expanduser(options["new_torrents_dir"]) + state_05_file = os.path.expanduser(options['state05']); + load_05(state_05_file, new_torrents_dir, options["all_paused"]) + + + + + + + + + + + + + + diff --git a/deluge/scripts/wiki_docgen.py b/deluge/scripts/wiki_docgen.py new file mode 100644 index 000000000..235083200 --- /dev/null +++ b/deluge/scripts/wiki_docgen.py @@ -0,0 +1,66 @@ +# +#generate docs for deluge-wiki +#client doc's For core. +# + +from deluge.core.core import Core +from deluge.ui.client import aclient +import pydoc +import inspect + + + +if False: #aclient non-core + methods = sorted([m for m in dir(aclient) if not m.startswith('_') + if not m in ['add_torrent_file', 'has_callback', 'get_method', + 'methodHelp','methodSignature','list_methods','add_torrent_file_binary']]) + + for m in methods: + func = getattr(aclient, m) + method_name = m + if method_name in dir(aclient): + func = getattr(aclient, method_name) + try: + params = inspect.getargspec(func)[0][1:] + except: + continue + + print "\n'''%s(%s): '''\n" %(method_name, ", ".join(params)) + print "%s" % pydoc.getdoc(func) + +if True: #baseclient/core + methods = sorted([m for m in dir(Core) if m.startswith("export")] + + ['export_add_torrent_file_binary'] #HACK + + ) + + for m in methods: + + method_name = m[7:] + if method_name in dir(aclient): + func = getattr(aclient, method_name) + else: + func = getattr(Core, m) + + params = inspect.getargspec(func)[0][1:] + if (aclient.has_callback(method_name) + and not method_name in ['add_torrent_file_binary']): + params = ["[callback]"] + params + + print "\n'''%s(%s): '''\n" %(method_name, ", ".join(params)) + print "%s" % pydoc.getdoc(func) + +if False: #plugin-manager + import WebUi + from WebUi.pluginmanager import PluginManager + + for m in methods: + func = getattr(PluginManager, m) + method_name = m + params = inspect.getargspec(func)[0][1:] + print "\n'''%s(%s): '''\n" %(method_name, ", ".join(params)) + print "%s" % pydoc.getdoc(func) + + + + diff --git a/deluge/ui/__init__.py b/deluge/ui/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/deluge/ui/client.py b/deluge/ui/client.py new file mode 100644 index 000000000..d8f4399fe --- /dev/null +++ b/deluge/ui/client.py @@ -0,0 +1,396 @@ +# +# client.py +# +# Copyright (C) 2007/2008 Andrew Resch ('andar') +# Copyright (C) 2008 Martijn Voncken +# +# 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 2 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 os.path +import socket + +import gobject + +import deluge.xmlrpclib as xmlrpclib + +import deluge.common +import deluge.error +from deluge.log import LOG as log + +class CoreProxy(gobject.GObject): + __gsignals__ = { + "new_core" : ( + gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, []), + "no_core" : ( + gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, []), + } + def __init__(self): + log.debug("CoreProxy init..") + gobject.GObject.__init__(self) + self._uri = None + self.rpc_core = None + self._multi = None + self._callbacks = [] + self._multi_timer = None + + def call(self, func, callback, *args): + if self.rpc_core is None or self._multi is None: + if self.rpc_core is None: + raise deluge.error.NoCoreError("The core proxy is invalid.") + return + _func = getattr(self._multi, func) + + if _func is not None: + if (func, args) in self._multi.get_call_list(): + index = self._multi.get_call_list().index((func, args)) + if callback not in self._callbacks[index]: + self._callbacks[index].append(callback) + else: + if len(args) == 0: + _func() + else: + _func(*args) + + self._callbacks.append([callback]) + + def do_multicall(self, block=False): + if len(self._callbacks) == 0: + return True + + if self._multi is not None and self.rpc_core is not None: + try: + try: + for i, ret in enumerate(self._multi()): + try: + for callback in self._callbacks[i]: + if block == False: + gobject.idle_add(callback, ret) + else: + callback(ret) + except: + pass + except (socket.error, xmlrpclib.ProtocolError), e: + self.set_core_uri(None) + except (deluge.xmlrpclib.Fault, Exception), e: + #self.set_core_uri(None) , disabled : there are many reasons for an exception ; not just an invalid core. + #todo : publish an exception event, ui's like gtk could popup a dialog for this. + log.warning("Multi-call Exception: %s:%s", e, getattr(e,"message",None)) + finally: + self._callbacks = [] + + self._multi = xmlrpclib.MultiCall(self.rpc_core) + + return True + + def set_core_uri(self, uri): + log.info("Setting core uri as %s", uri) + + if uri == None and self._uri != None: + self._uri = None + self.rpc_core = None + self._multi = None + try: + gobject.source_remove(self._multi_timer) + except: + pass + self.emit("no_core") + return + + if uri != self._uri and self._uri != None: + self.rpc_core = None + self._multi = None + try: + gobject.source_remove(self._multi_timer) + except: + pass + self.emit("no_core") + + self._uri = uri + # Get a new core + self.get_rpc_core() + + def get_core_uri(self): + """Returns the URI of the core currently being used.""" + return self._uri + + def get_rpc_core(self): + if self.rpc_core is None and self._uri is not None: + log.debug("Creating ServerProxy..") + self.rpc_core = xmlrpclib.ServerProxy(self._uri, allow_none=True) + self._multi = xmlrpclib.MultiCall(self.rpc_core) + self._multi_timer = gobject.timeout_add(200, self.do_multicall) + # Call any callbacks registered + self.emit("new_core") + + return self.rpc_core + +_core = CoreProxy() + +class BaseClient(object): + """ + wraps all calls to core/coreproxy + base for AClient and SClient + """ + no_callback_list = ["add_torrent_url", "pause_all_torrents", + "resume_all_torrents", "set_config", "enable_plugin", + "disable_plugin", "set_torrent_trackers", + "set_torrent_max_connections", "set_torrent_max_upload_slots", + "set_torrent_max_upload_speed", "set_torrent_max_download_speed", + "set_torrent_private_flag", "set_torrent_file_priorities", + "block_ip_range", "remove_torrent", "pause_torrent", "move_storage", + "resume_torrent", "force_reannounce", "force_recheck", + "deregister_client", "register_client", "add_torrent_file", + "set_torrent_prioritize_first_last", "set_torrent_auto_managed", + "set_torrent_stop_ratio", "set_torrent_stop_at_ratio", + "set_torrent_remove_at_ratio"] + + def __init__(self): + self.core = _core + + #xml-rpc introspection + def list_methods(self): + registered = self.core.rpc_core.system.listMethods() + return sorted(registered) + + def methodSignature(self, method_name): + "broken :(" + return self.core.rpc_core.system.methodSignature(method_name) + + def methodHelp(self, method_name): + return self.core.rpc_core.system.methodHelp(method_name) + + #wrappers, getattr + def get_method(self, method_name): + "Override this in subclass." + raise NotImplementedError() + + def __getattr__(self, method_name): + return self.get_method(method_name) + #raise AttributeError("no attr/method named:%s" % attr) + + #custom wrapped methods: + def add_torrent_file(self, torrent_files, torrent_options=None): + """Adds torrent files to the core + Expects a list of torrent files + A list of torrent_option dictionaries in the same order of torrent_files + """ + if torrent_files is None: + log.debug("No torrent files selected..") + return + log.debug("Attempting to add torrent files: %s", torrent_files) + for torrent_file in torrent_files: + # Open the .torrent file for reading because we need to send it's + # contents to the core. + try: + f = open(torrent_file, "rb") + except Exception, e: + log.warning("Unable to open %s: %s", torrent_file, e) + continue + + # Get the filename because the core doesn't want a path. + (path, filename) = os.path.split(torrent_file) + fdump = xmlrpclib.Binary(f.read()) + f.close() + + # Get the options for the torrent + if torrent_options != None: + try: + options = torrent_options[torrent_files.index(torrent_file)] + except: + options = None + else: + options = None + self.get_method("add_torrent_file")(filename, fdump, options) + + def add_torrent_file_binary(self, filename, fdump, options = None): + """ + Core-wrapper. + Adds 1 torrent file to the core. + Expects fdump as a bytestring (== result of f.read()). + """ + fdump_xmlrpc = xmlrpclib.Binary(fdump) + self.get_method("add_torrent_file")(filename, fdump_xmlrpc, options) + + #utility: + def has_callback(self, method_name): + return not (method_name in self.no_callback_list) + + def is_localhost(self): + """Returns True if core is a localhost""" + # Get the uri + uri = self.core.get_core_uri() + if uri != None: + # Get the host + host = uri[7:].split(":")[0] + if host == "localhost" or host == "127.0.0.1": + return True + return False + + def get_core_uri(self): + """Get the core URI""" + return self.core.get_core_uri() + + def set_core_uri(self, uri='http://localhost:58846'): + """Sets the core uri""" + return self.core.set_core_uri(uri) + + def connected(self): + """Returns True if connected to a host, and False if not.""" + if self.get_core_uri() != None: + return True + return False + + def shutdown(self): + """Shutdown the core daemon""" + try: + self.core.call("shutdown", None) + self.core.do_multicall(block=False) + finally: + self.set_core_uri(None) + + #events: + def connect_on_new_core(self, callback): + """Connect a callback whenever a new core is connected to.""" + return self.core.connect("new_core", callback) + + def connect_on_no_core(self, callback): + """Connect a callback whenever the core is disconnected from.""" + return self.core.connect("no_core", callback) + +class SClient(BaseClient): + """ + sync proxy + """ + def get_method(self, method_name): + return getattr(self.core.rpc_core, method_name) + +class AClient(BaseClient): + """ + async proxy + """ + def get_method(self, method_name): + if not self.has_callback(method_name): + def async_proxy_nocb(*args, **kwargs): + return self.core.call(method_name, None, *args, **kwargs) + return async_proxy_nocb + else: + def async_proxy(*args, **kwargs): + return self.core.call(method_name, *args, **kwargs) + return async_proxy + + def force_call(self, block=True): + """Forces the multicall batch to go now and not wait for the timer. This + call also blocks until all callbacks have been dealt with.""" + self.core.do_multicall(block=block) + +sclient = SClient() +aclient = AClient() + +#------------------------------------------------------------------------------ +#tests: +#------------------------------------------------------------------------------ + +def test_introspection(): + print "*start introspection test*" + sclient.set_core_uri() + print "list_methods", sclient.list_methods() + print "sig of block_ip_range", sclient.methodSignature('block_ip_range') + print "doc of block_ip_range", sclient.methodHelp('block_ip_range') + +def test_sync(): + print "*start sync test*" + sclient.set_core_uri() + + #get list of torrents and display the 1st. + torrent_ids = sclient.get_session_state() + print "session_state():", torrent_ids + print ("get_torrent_status(%s):" % torrent_ids[0], + sclient.get_torrent_status(torrent_ids[0], [])) + + sclient.pause_torrent(torrent_ids) + + print "paused:", [ + sclient.get_torrent_status(id, ['paused'])['paused'] + for id in torrent_ids] + + sclient.resume_torrent(torrent_ids) + print "resumed:", [ + sclient.get_torrent_status(id, ['paused'])['paused'] + for id in torrent_ids] + +def test_async(): + print "*start async test*" + torrent_ids = [] + + #callbacks: + def cb_session_state(temp_torrent_list): + print "session_state:" , temp_torrent_list + torrent_ids.extend(temp_torrent_list) + + def cb_torrent_status_full(status): + print "\ntorrent_status_full=", status + + def cb_torrent_status_paused(torrent_state): + print "(paused=%s)," % torrent_state['paused'], + + #/callbacks + + aclient.set_core_uri() + aclient.get_session_state(cb_session_state) + + print "force_call 1" + aclient.force_call(block=True) + print "end force_call 1:", len(torrent_ids) + + + #has_callback+multicall + aclient.pause_torrent(torrent_ids) + aclient.force_call(block=True) + for id in torrent_ids: + aclient.get_torrent_status(cb_torrent_status_paused, id , ['paused']) + + aclient.get_torrent_status(cb_torrent_status_full, torrent_ids[0], []) + + print "force_call 2" + aclient.force_call(block=True) + print "end force-call 2" + + + + print "resume:" + aclient.resume_torrent(torrent_ids) + for id in torrent_ids: + aclient.get_torrent_status(cb_torrent_status_paused, id , ['paused']) + + aclient.force_call(block=True) + +if __name__ == "__main__": + test_introspection() + test_sync() + test_async() diff --git a/deluge/ui/gtkui/__init__.py b/deluge/ui/gtkui/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/deluge/ui/gtkui/aboutdialog.py b/deluge/ui/gtkui/aboutdialog.py new file mode 100644 index 000000000..97b88557b --- /dev/null +++ b/deluge/ui/gtkui/aboutdialog.py @@ -0,0 +1,83 @@ +# +# aboutdialog.py +# +# Copyright (C) 2007 Marcos Pinto ('markybob') +# +# 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 2 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 pygtk +pygtk.require('2.0') +import gtk +import pkg_resources + +import deluge.common +from deluge.ui.client import aclient as client + +class AboutDialog: + def __init__(self): + # Get the glade file for the about dialog + def url_hook(dialog, url): + client.open_url_in_browser(url) + gtk.about_dialog_set_url_hook(url_hook) + self.about = gtk.AboutDialog() + self.about.set_position(gtk.WIN_POS_CENTER) + self.about.set_name("Deluge") + self.about.set_program_name("Deluge") + + # Get the version and revision numbers + rev = deluge.common.get_revision() + version = deluge.common.get_version() + if rev != "": + version = version + "r" + rev + self.about.set_copyright(u'Copyright \u00A9 2007-2008 Andrew Resch') + self.about.set_comments("A peer-to-peer file sharing program utilizing the Bittorrent protocol.") + self.about.set_version(version) + self.about.set_authors(["Andrew Resch", "Marcos Pinto", + "Sadrul Habib Chowdhury", "Martijn Voncken"]) + self.about.set_artists(["Andrew Wedderburn", "Andrew Resch"]) + self.about.set_translator_credits(_("translator-credits")) + self.about.set_wrap_license(True) + self.about.set_license(_("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 2 of the License, 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, see .")) + self.about.set_website("http://deluge-torrent.org") + self.about.set_website_label("http://deluge-torrent.org") + self.about.set_icon(deluge.common.get_logo(32)) + self.about.set_logo(gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("deluge-about.png"))) + + def run(self): + self.about.show_all() + self.about.run() + self.about.destroy() diff --git a/deluge/ui/gtkui/addtorrentdialog.py b/deluge/ui/gtkui/addtorrentdialog.py new file mode 100644 index 000000000..d5c1e5302 --- /dev/null +++ b/deluge/ui/gtkui/addtorrentdialog.py @@ -0,0 +1,614 @@ +# +# addtorrentdialog.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 pygtk +pygtk.require('2.0') +import gtk, gtk.glade +import gettext +import gobject + +import pkg_resources + +from deluge.ui.client import aclient as client +import deluge.component as component +import deluge.ui.gtkui.listview as listview +from deluge.configmanager import ConfigManager +from deluge.log import LOG as log +import deluge.common + +class AddTorrentDialog(component.Component): + def __init__(self): + component.Component.__init__(self, "AddTorrentDialog") + self.glade = gtk.glade.XML( + pkg_resources.resource_filename( + "deluge.ui.gtkui", "glade/add_torrent_dialog.glade")) + + self.dialog = self.glade.get_widget("dialog_add_torrent") + + self.glade.signal_autoconnect({ + "on_button_file_clicked": self._on_button_file_clicked, + "on_button_url_clicked": self._on_button_url_clicked, + "on_button_hash_clicked": self._on_button_hash_clicked, + "on_button_remove_clicked": self._on_button_remove_clicked, + "on_button_trackers_clicked": self._on_button_trackers_clicked, + "on_button_cancel_clicked": self._on_button_cancel_clicked, + "on_button_add_clicked": self._on_button_add_clicked, + "on_button_apply_clicked": self._on_button_apply_clicked, + "on_button_revert_clicked": self._on_button_revert_clicked + }) + + self.torrent_liststore = gtk.ListStore(str, str, str) + #download?, path, filesize, sequence number, inconsistent? + self.files_treestore = gtk.TreeStore(bool, str, gobject.TYPE_UINT64, + gobject.TYPE_INT64, bool, str) + # Holds the files info + self.files = {} + self.infos = {} + self.core_config = {} + self.options = {} + self.previous_selected_torrent = None + + + self.listview_torrents = self.glade.get_widget("listview_torrents") + self.listview_files = self.glade.get_widget("listview_files") + + render = gtk.CellRendererText() + column = gtk.TreeViewColumn(_("Torrent"), render, text=1) + self.listview_torrents.append_column(column) + + render = gtk.CellRendererToggle() + render.connect("toggled", self._on_file_toggled) + column = gtk.TreeViewColumn(None, render, active=0, inconsistent=4) + self.listview_files.append_column(column) + + column = gtk.TreeViewColumn(_("Filename")) + render = gtk.CellRendererPixbuf() + column.pack_start(render, False) + column.add_attribute(render, "stock-id", 5) + render = gtk.CellRendererText() + column.pack_start(render, True) + column.add_attribute(render, "text", 1) + column.set_expand(True) + self.listview_files.append_column(column) + + render = gtk.CellRendererText() + column = gtk.TreeViewColumn(_("Size")) + column.pack_start(render) + column.set_cell_data_func(render, listview.cell_data_size, 2) + self.listview_files.append_column(column) + + self.listview_torrents.set_model(self.torrent_liststore) + self.listview_files.set_model(self.files_treestore) + + self.listview_files.get_selection().set_mode(gtk.SELECTION_MULTIPLE) + self.listview_torrents.get_selection().connect("changed", + self._on_torrent_changed) + + # Get default config values from the core + self.core_keys = [ + "compact_allocation", + "max_connections_per_torrent", + "max_upload_slots_per_torrent", + "max_upload_speed_per_torrent", + "max_download_speed_per_torrent", + "prioritize_first_last_pieces", + "download_location", + "add_paused" + ] + self.core_config = {} + + def start(self): + self.update_core_config() + + def show(self, focus=False): + self.update_core_config() + + if client.is_localhost(): + self.glade.get_widget("button_location").show() + self.glade.get_widget("entry_download_path").hide() + else: + self.glade.get_widget("button_location").hide() + self.glade.get_widget("entry_download_path").show() + + self.dialog.set_transient_for(component.get("MainWindow").window) + self.dialog.present() + if focus: + self.dialog.window.focus() + + return None + + def hide(self): + self.dialog.hide() + self.files = {} + self.infos = {} + self.options = {} + self.previous_selected_torrent = None + self.torrent_liststore.clear() + self.files_treestore.clear() + self.dialog.set_transient_for(component.get("MainWindow").window) + return None + + def update_core_config(self): + self.core_config = {} + # Send requests to the core for these config values + for key in self.core_keys: + client.get_config_value(self._on_config_value, key) + + # Force a call to the core because we need this data now + client.force_call() + self.set_default_options() + + def _on_config_value(self, value): + for key in self.core_keys: + if not self.core_config.has_key(key): + self.core_config[key] = value + break + + def add_from_files(self, filenames): + import deluge.libtorrent as lt + import os.path + new_row = None + + for filename in filenames: + # Get the torrent data from the torrent file + try: + log.debug("Attempting to open %s for add.", filename) + _file = open(filename, "rb") + filedump = _file.read() + if not filedump: + log.warning("Torrent appears to be corrupt!") + continue + filedump = lt.bdecode(filedump) + _file.close() + except Exception, e: + log.warning("Unable to open %s: e", filename, e) + continue + + try: + info = lt.torrent_info(filedump) + except RuntimeError, e: + log.warning("Torrent appears to be corrupt!") + continue + + if str(info.info_hash()) in self.infos: + log.debug("Torrent already in list!") + continue + + # Get list of files from torrent info + files = [] + for f in info.files(): + files.append({ + 'path': f.path, + 'size': f.size, + 'download': True + }) + + name = "%s (%s)" % (info.name(), os.path.split(filename)[-1]) + new_row = self.torrent_liststore.append( + [str(info.info_hash()), name, filename]) + self.files[str(info.info_hash())] = files + self.infos[str(info.info_hash())] = info + + (model, row) = self.listview_torrents.get_selection().get_selected() + if not row and new_row: + self.listview_torrents.get_selection().select_iter(new_row) + + def _on_torrent_changed(self, treeselection): + (model, row) = treeselection.get_selected() + self.files_treestore.clear() + + if row is None: + return + + # Update files list + files_list = self.files[model.get_value(row, 0)] + + self.prepare_file_store(files_list) + + if self.core_config == {}: + self.update_core_config() + + # Save the previous torrents options + self.save_torrent_options() + # Update the options frame + self.update_torrent_options(model.get_value(row, 0)) + + self.previous_selected_torrent = row + + def prepare_file_store(self, files): + split_files = { } + i = 0 + for file in files: + self.prepare_file(file, file["path"], i, split_files) + i += 1 + self.add_files(None, split_files) + + def prepare_file(self, file, file_name, file_num, files_storage): + first_slash_index = file_name.find("/") + if first_slash_index == -1: + files_storage[file_name] = (file_num, file) + else: + file_name_chunk = file_name[:first_slash_index+1] + if file_name_chunk not in files_storage: + files_storage[file_name_chunk] = { } + self.prepare_file(file, file_name[first_slash_index+1:], + file_num, files_storage[file_name_chunk]) + + def add_files(self, parent_iter, split_files): + ret = 0 + for key,value in split_files.iteritems(): + if key.endswith("/"): + chunk_iter = self.files_treestore.append(parent_iter, + [True, key, 0, -1, False, gtk.STOCK_DIRECTORY]) + chunk_size = self.add_files(chunk_iter, value) + self.files_treestore.set(chunk_iter, 2, chunk_size) + ret += chunk_size + else: + self.files_treestore.append(parent_iter, [True, key, + value[1]["size"], value[0], False, gtk.STOCK_FILE]) + ret += value[1]["size"] + return ret + + def update_torrent_options(self, torrent_id): + if torrent_id not in self.options: + self.set_default_options() + return + + options = self.options[torrent_id] + + if client.is_localhost(): + self.glade.get_widget("button_location").set_current_folder( + options["download_location"]) + else: + self.glade.get_widget("entry_download_path").set_text( + options["download_location"]) + + self.glade.get_widget("radio_compact").set_active( + options["compact_allocation"]) + self.glade.get_widget("spin_maxdown").set_value( + options["max_download_speed_per_torrent"]) + self.glade.get_widget("spin_maxup").set_value( + options["max_upload_speed_per_torrent"]) + self.glade.get_widget("spin_maxconnections").set_value( + options["max_connections_per_torrent"]) + self.glade.get_widget("spin_maxupslots").set_value( + options["max_upload_slots_per_torrent"]) + self.glade.get_widget("chk_paused").set_active( + options["add_paused"]) + self.glade.get_widget("chk_prioritize").set_active( + options["prioritize_first_last_pieces"]) + + def save_torrent_options(self, row=None): + # Keeps the torrent options dictionary up-to-date with what the user has + # selected. + if row is None: + row = self.previous_selected_torrent + if row is None or not self.torrent_liststore.iter_is_valid(row): + return + + torrent_id = self.torrent_liststore.get_value(row, 0) + + options = {} + if client.is_localhost(): + options["download_location"] = \ + self.glade.get_widget("button_location").get_current_folder() + else: + options["download_location"] = \ + self.glade.get_widget("entry_download_path").get_text() + options["compact_allocation"] = \ + self.glade.get_widget("radio_compact").get_active() + options["max_download_speed_per_torrent"] = \ + self.glade.get_widget("spin_maxdown").get_value() + options["max_upload_speed_per_torrent"] = \ + self.glade.get_widget("spin_maxup").get_value() + options["max_connections_per_torrent"] = \ + self.glade.get_widget("spin_maxconnections").get_value_as_int() + options["max_upload_slots_per_torrent"] = \ + self.glade.get_widget("spin_maxupslots").get_value_as_int() + options["add_paused"] = \ + self.glade.get_widget("chk_paused").get_active() + options["prioritize_first_last_pieces"] = \ + self.glade.get_widget("chk_prioritize").get_active() + options["default_private"] = \ + self.glade.get_widget("chk_private").get_active() + + self.options[torrent_id] = options + + # Save the file priorities + files_priorities = self.build_priorities( + self.files_treestore.get_iter_first(), {}) + + for i, file_dict in enumerate(self.files[torrent_id]): + file_dict["download"] = files_priorities[i] + + def build_priorities(self, iter, priorities): + while iter is not None: + if self.files_treestore.iter_has_child(iter): + self.build_priorities(self.files_treestore.iter_children(iter), + priorities) + elif not self.files_treestore.get_value(iter, 1).endswith("/"): + priorities[self.files_treestore.get_value(iter, 3)] = self.files_treestore.get_value(iter, 0) + iter = self.files_treestore.iter_next(iter) + return priorities + + def set_default_options(self): + if client.is_localhost(): + self.glade.get_widget("button_location").set_current_folder( + self.core_config["download_location"]) + else: + self.glade.get_widget("entry_download_path").set_text( + self.core_config["download_location"]) + + self.glade.get_widget("radio_compact").set_active( + self.core_config["compact_allocation"]) + self.glade.get_widget("spin_maxdown").set_value( + self.core_config["max_download_speed_per_torrent"]) + self.glade.get_widget("spin_maxup").set_value( + self.core_config["max_upload_speed_per_torrent"]) + self.glade.get_widget("spin_maxconnections").set_value( + self.core_config["max_connections_per_torrent"]) + self.glade.get_widget("spin_maxupslots").set_value( + self.core_config["max_upload_slots_per_torrent"]) + self.glade.get_widget("chk_paused").set_active( + self.core_config["add_paused"]) + self.glade.get_widget("chk_prioritize").set_active( + self.core_config["prioritize_first_last_pieces"]) + + def get_file_priorities(self, torrent_id): + # A list of priorities + files_list = [] + + for file_dict in self.files[torrent_id]: + if file_dict["download"] == False: + files_list.append(0) + else: + files_list.append(1) + + return files_list + + def _on_file_toggled(self, render, path): + (model, paths) = self.listview_files.get_selection().get_selected_rows() + if len(paths) > 1: + for path in paths: + row = model.get_iter(path) + self.toggle_iter(row) + else: + row = model.get_iter(path) + self.toggle_iter(row) + self.update_treeview_toggles(self.files_treestore.get_iter_first()) + + def toggle_iter(self, iter, toggle_to=None): + if toggle_to is None: + toggle_to = not self.files_treestore.get_value(iter, 0) + self.files_treestore.set_value(iter, 0, toggle_to) + if self.files_treestore.iter_has_child(iter): + child = self.files_treestore.iter_children(iter) + while child is not None: + self.toggle_iter(child, toggle_to) + child = self.files_treestore.iter_next(child) + + def update_treeview_toggles(self, iter): + TOGGLE_INCONSISTENT = -1 + this_level_toggle = None + while iter is not None: + if self.files_treestore.iter_has_child(iter): + toggle = self.update_treeview_toggles( + self.files_treestore.iter_children(iter)) + if toggle == TOGGLE_INCONSISTENT: + self.files_treestore.set_value(iter, 4, True) + else: + self.files_treestore.set_value(iter, 0, toggle) + #set inconsistent to false + self.files_treestore.set_value(iter, 4, False) + else: + toggle = self.files_treestore.get_value(iter, 0) + if this_level_toggle is None: + this_level_toggle = toggle + elif this_level_toggle != toggle: + this_level_toggle = TOGGLE_INCONSISTENT + iter = self.files_treestore.iter_next(iter) + return this_level_toggle + + def _on_button_file_clicked(self, widget): + log.debug("_on_button_file_clicked") + # Setup the filechooserdialog + chooser = gtk.FileChooserDialog(_("Choose a .torrent file"), + None, + gtk.FILE_CHOOSER_ACTION_OPEN, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, + gtk.RESPONSE_OK)) + + chooser.set_transient_for(self.dialog) + chooser.set_select_multiple(True) + chooser.set_property("skip-taskbar-hint", True) + + # Add .torrent and * file filters + file_filter = gtk.FileFilter() + file_filter.set_name(_("Torrent files")) + file_filter.add_pattern("*." + "torrent") + chooser.add_filter(file_filter) + file_filter = gtk.FileFilter() + file_filter.set_name(_("All files")) + file_filter.add_pattern("*") + chooser.add_filter(file_filter) + + # Load the 'default_load_path' from the config + self.config = ConfigManager("gtkui.conf") + if self.config.get("default_load_path") is not None: + chooser.set_current_folder(self.config.get("default_load_path")) + + # Run the dialog + response = chooser.run() + + if response == gtk.RESPONSE_OK: + result = chooser.get_filenames() + self.config.set("default_load_path", chooser.get_current_folder()) + else: + chooser.destroy() + return + + chooser.destroy() + self.add_from_files(result) + + def _on_button_url_clicked(self, widget): + log.debug("_on_button_url_clicked") + dialog = self.glade.get_widget("url_dialog") + entry = self.glade.get_widget("entry_url") + + dialog.set_default_response(gtk.RESPONSE_OK) + dialog.set_transient_for(self.dialog) + entry.grab_focus() + + if deluge.common.windows_check(): + import win32clipboard as clip + import win32con + clip.OpenClipboard() + text = clip.GetClipboardData(win32con.CF_UNICODETEXT) + clip.CloseClipboard() + else: + clip = gtk.clipboard_get(selection='PRIMARY') + text = clip.wait_for_text() + if text: + text = text.strip() + if deluge.common.is_url(text): + entry.set_text(text) + + dialog.show_all() + response = dialog.run() + + if response == gtk.RESPONSE_OK: + url = entry.get_text().decode("utf_8") + else: + url = None + + # This is where we need to fetch the .torrent file from the URL and + # add it to the list. + log.debug("url: %s", url) + if url != None: + self.add_from_url(url) + + entry.set_text("") + dialog.hide() + + def add_from_url(self, url): + gobject.idle_add(self._download_from_url, url) + + def _download_from_url(self, url): + import urllib + import tempfile + import os.path + tmp_file = os.path.join(tempfile.gettempdir(), url.split("/")[-1]) + filename, headers = urllib.urlretrieve(url, tmp_file) + log.debug("filename: %s", filename) + self.add_from_files([filename]) + + def _on_button_hash_clicked(self, widget): + log.debug("_on_button_hash_clicked") + + def _on_button_remove_clicked(self, widget): + log.debug("_on_button_remove_clicked") + (model, row) = self.listview_torrents.get_selection().get_selected() + if row is None: + return + + torrent_id = model.get_value(row, 0) + + model.remove(row) + del self.files[torrent_id] + del self.infos[torrent_id] + + def _on_button_trackers_clicked(self, widget): + log.debug("_on_button_trackers_clicked") + + def _on_button_cancel_clicked(self, widget): + log.debug("_on_button_cancel_clicked") + self.hide() + + def _on_button_add_clicked(self, widget): + log.debug("_on_button_add_clicked") + # Save the options for selected torrent prior to adding + (model, row) = self.listview_torrents.get_selection().get_selected() + if row is not None: + self.save_torrent_options(row) + + torrent_filenames = [] + torrent_options = [] + + row = self.torrent_liststore.get_iter_first() + while row != None: + torrent_id = self.torrent_liststore.get_value(row, 0) + filename = self.torrent_liststore.get_value(row, 2) + try: + options = self.options[torrent_id] + except: + options = None + + file_priorities = self.get_file_priorities(torrent_id) + if options != None: + options["file_priorities"] = file_priorities + + torrent_filenames.append(filename) + torrent_options.append(options) + + row = self.torrent_liststore.iter_next(row) + + client.add_torrent_file(torrent_filenames, torrent_options) + client.force_call() + self.hide() + + def _on_button_apply_clicked(self, widget): + log.debug("_on_button_apply_clicked") + (model, row) = self.listview_torrents.get_selection().get_selected() + if row is None: + return + + self.save_torrent_options(row) + + # The options we want all the torrents to have + options = self.options[model.get_value(row, 0)] + + # Set all the torrent options + row = model.get_iter_first() + while row != None: + torrent_id = model.get_value(row, 0) + self.options[torrent_id] = options + row = model.iter_next(row) + + def _on_button_revert_clicked(self, widget): + log.debug("_on_button_revert_clicked") + (model, row) = self.listview_torrents.get_selection().get_selected() + if row is None: + return + + del self.options[model.get_value(row, 0)] + self.set_default_options() diff --git a/deluge/ui/gtkui/addtorrenturl.py b/deluge/ui/gtkui/addtorrenturl.py new file mode 100644 index 000000000..4b07fc8cc --- /dev/null +++ b/deluge/ui/gtkui/addtorrenturl.py @@ -0,0 +1,80 @@ +# +# addtorrenturl.py +# +# Copyright (C) 2007 Marcos Pinto ('markybob') +# +# 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 2 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 pygtk +pygtk.require('2.0') +import gtk +import gettext + +import deluge.common +import pkg_resources + +class AddTorrentUrl: + def __init__(self, parent=None): + """Set up url dialog""" + self.dlg = gtk.Dialog(_("Add torrent from URL"), None, 0, \ + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,gtk.STOCK_OK, gtk.RESPONSE_OK)) + self.dlg.set_default_response(gtk.RESPONSE_OK) + self.dlg.set_icon(deluge.common.get_logo(32)) + self.dlg.set_default_response(1) + label = gtk.Label(_("Enter the URL of the .torrent to download")) + self.entry = gtk.Entry() + self.entry.connect("activate", lambda w : self.dlg.response\ + (gtk.RESPONSE_OK)) + self.dlg.vbox.pack_start(label) + self.dlg.vbox.pack_start(self.entry) + if deluge.common.windows_check(): + import win32clipboard as clip + import win32con + clip.OpenClipboard() + text = clip.GetClipboardData(win32con.CF_UNICODETEXT) + clip.CloseClipboard() + else: + clip = gtk.clipboard_get(selection='PRIMARY') + text = clip.wait_for_text() + if text: + text = text.strip() + if deluge.common.is_url(text): + self.entry.set_text(text) + + def run(self): + """Show url dialog and add torrent""" + self.dlg.show_all() + self.response = self.dlg.run() + if self.response == gtk.RESPONSE_OK: + url = self.entry.get_text().decode("utf_8") + self.dlg.destroy() + return url + else: + self.dlg.destroy() + return None diff --git a/deluge/ui/gtkui/connectionmanager.py b/deluge/ui/gtkui/connectionmanager.py new file mode 100644 index 000000000..70ab8ebc9 --- /dev/null +++ b/deluge/ui/gtkui/connectionmanager.py @@ -0,0 +1,511 @@ +# +# connectionmanager.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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, gtk.glade +import pkg_resources +import gobject +import socket +import os +import time +import threading + +import deluge.component as component +import deluge.xmlrpclib as xmlrpclib +import deluge.common +from deluge.ui.client import aclient as client +from deluge.configmanager import ConfigManager +from deluge.log import LOG as log + +DEFAULT_CONFIG = { + "hosts": ["localhost:58846"] +} + +HOSTLIST_COL_PIXBUF = 0 +HOSTLIST_COL_URI = 1 +HOSTLIST_COL_STATUS = 2 + +HOSTLIST_STATUS = [ + "Offline", + "Online", + "Connected" +] + +if deluge.common.windows_check(): + import win32api + +class ConnectionManager(component.Component): + def __init__(self): + component.Component.__init__(self, "ConnectionManager") + # Get the glade file for the connection manager + self.glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/connection_manager.glade")) + + self.window = component.get("MainWindow") + self.config = ConfigManager("hostlist.conf", DEFAULT_CONFIG) + self.gtkui_config = ConfigManager("gtkui.conf") + self.connection_manager = self.glade.get_widget("connection_manager") + # Make the Connection Manager window a transient for the main window. + self.connection_manager.set_transient_for(self.window.window) + self.hostlist = self.glade.get_widget("hostlist") + self.connection_manager.set_icon(deluge.common.get_logo(32)) + + self.glade.get_widget("image1").set_from_pixbuf( + deluge.common.get_logo(32)) + + self.liststore = gtk.ListStore(gtk.gdk.Pixbuf, str, int) + + # Holds the online status of hosts + self.online_status = {} + + # Fill in hosts from config file + for host in self.config["hosts"]: + row = self.liststore.append() + self.liststore.set_value(row, HOSTLIST_COL_URI, host) + + # Setup host list treeview + self.hostlist.set_model(self.liststore) + render = gtk.CellRendererPixbuf() + column = gtk.TreeViewColumn( + "Status", render, pixbuf=HOSTLIST_COL_PIXBUF) + self.hostlist.append_column(column) + render = gtk.CellRendererText() + column = gtk.TreeViewColumn("Host", render, text=HOSTLIST_COL_URI) + self.hostlist.append_column(column) + + self.glade.signal_autoconnect({ + "on_button_addhost_clicked": self.on_button_addhost_clicked, + "on_button_removehost_clicked": self.on_button_removehost_clicked, + "on_button_startdaemon_clicked": \ + self.on_button_startdaemon_clicked, + "on_button_close_clicked": self.on_button_close_clicked, + "on_button_connect_clicked": self.on_button_connect_clicked, + "on_chk_autoconnect_toggled": self.on_chk_autoconnect_toggled, + "on_chk_autostart_toggled": self.on_chk_autostart_toggled, + "on_chk_donotshow_toggled": self.on_chk_donotshow_toggled + }) + + self.connection_manager.connect("delete-event", self.on_delete_event) + # Connect to the 'changed' event of TreeViewSelection to get selection + # changes. + self.hostlist.get_selection().connect("changed", + self.on_selection_changed) + + # If classic mode is set, we just start up a localhost daemon and connect to it + if self.gtkui_config["classic_mode"]: + uri = "http://localhost:58846" + if deluge.common.windows_check(): + win32api.WinExec("deluged -p 58846") + else: + os.popen("deluged -p 58846") + time.sleep(0.1) + # We need to wait for the host to start before connecting + while not self.test_online_status(uri): + time.sleep(0.01) + client.set_core_uri(uri) + self.hide() + return + + # This controls the timer, if it's set to false the update timer will stop. + self._do_update = True + self._update_list() + + # Auto connect to a host if applicable + if self.gtkui_config["autoconnect"] and \ + self.gtkui_config["autoconnect_host_uri"] != None: + uri = self.gtkui_config["autoconnect_host_uri"] + # Make sure the uri is proper + if uri[:7] != "http://": + uri = "http://" + uri + if self.test_online_status(uri): + # Host is online, so lets connect + client.set_core_uri(uri) + self.hide() + elif self.gtkui_config["autostart_localhost"]: + # Check to see if we are trying to connect to a localhost + if uri[7:].split(":")[0] == "localhost" or \ + uri[7:].split(":")[0] == "127.0.0.1": + # This is a localhost, so lets try to start it + port = uri[7:].split(":")[1] + # First add it to the list + self.add_host("localhost", port) + if deluge.common.windows_check(): + win32api.WinExec("deluged -p %s" % port) + else: + os.popen("deluged -p %s" % port) + # We need to wait for the host to start before connecting + while not self.test_online_status(uri): + time.sleep(0.01) + client.set_core_uri(uri) + self.hide() + + def start(self): + if self.gtkui_config["autoconnect"]: + # We need to update the autoconnect_host_uri on connection to host + # start() gets called whenever we get a new connection to a host + self.gtkui_config["autoconnect_host_uri"] = client.get_core_uri() + + def show(self): + # Set the checkbuttons according to config + self.glade.get_widget("chk_autoconnect").set_active( + self.gtkui_config["autoconnect"]) + self.glade.get_widget("chk_autostart").set_active( + self.gtkui_config["autostart_localhost"]) + self.glade.get_widget("chk_donotshow").set_active( + not self.gtkui_config["show_connection_manager_on_start"]) + + # Setup timer to update host status + self._update_timer = gobject.timeout_add(1000, self._update_list) + self._update_list() + self._update_list() + self.connection_manager.show_all() + + def hide(self): + self.connection_manager.hide() + self._do_update = False + try: + gobject.source_remove(self._update_timer) + except AttributeError: + # We are probably trying to hide the window without having it showed + # first. OK to ignore. + pass + + def _update_list(self): + """Updates the host status""" + def update_row(model=None, path=None, row=None, columns=None): + uri = model.get_value(row, HOSTLIST_COL_URI) + uri = "http://" + uri + threading.Thread(target=self.test_online_status, args=(uri,)).start() + try: + online = self.online_status[uri] + except: + online = False + + if online: + image = gtk.STOCK_YES + online = HOSTLIST_STATUS.index("Online") + else: + image = gtk.STOCK_NO + online = HOSTLIST_STATUS.index("Offline") + + if uri == current_uri: + # We are connected to this host, so lets display the connected + # icon. + image = gtk.STOCK_CONNECT + online = HOSTLIST_STATUS.index("Connected") + + pixbuf = self.connection_manager.render_icon( + image, gtk.ICON_SIZE_MENU) + + model.set_value(row, HOSTLIST_COL_PIXBUF, pixbuf) + model.set_value(row, HOSTLIST_COL_STATUS, online) + + current_uri = client.get_core_uri() + self.liststore.foreach(update_row) + # Update the buttons + self.update_buttons() + + # See if there is any row selected + paths = self.hostlist.get_selection().get_selected_rows()[1] + if len(paths) < 1: + # And there is at least 1 row + if self.liststore.iter_n_children(None) > 0: + # Then select the first row + self.hostlist.get_selection().select_iter(self.liststore.get_iter_first()) + return self._do_update + + def update_buttons(self): + """Updates the buttons based on selection""" + if self.liststore.iter_n_children(None) < 1: + # There is nothing in the list + self.glade.get_widget("button_startdaemon").set_sensitive(True) + self.glade.get_widget("button_connect").set_sensitive(False) + self.glade.get_widget("button_removehost").set_sensitive(False) + self.glade.get_widget("image_startdaemon").set_from_stock( + gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU) + self.glade.get_widget("label_startdaemon").set_text( + "_Start Daemon") + self.glade.get_widget("label_startdaemon").set_use_underline( + True) + + # Get the selected row's URI + paths = self.hostlist.get_selection().get_selected_rows()[1] + # If nothing is selected, just return + if len(paths) < 1: + return + row = self.liststore.get_iter(paths[0]) + uri = self.liststore.get_value(row, HOSTLIST_COL_URI) + status = self.liststore.get_value(row, HOSTLIST_COL_STATUS) + + # Check to see if a localhost is selected + localhost = False + if uri.split(":")[0] == "localhost" or uri.split(":")[0] == "127.0.0.1": + localhost = True + + # Make actual URI string + uri = "http://" + uri + + # Make sure buttons are sensitive at start + self.glade.get_widget("button_startdaemon").set_sensitive(True) + self.glade.get_widget("button_connect").set_sensitive(True) + self.glade.get_widget("button_removehost").set_sensitive(True) + + # See if this is the currently connected URI + if status == HOSTLIST_STATUS.index("Connected"): + # Display a disconnect button if we're connected to this host + self.glade.get_widget("button_connect").set_label("gtk-disconnect") + self.glade.get_widget("button_removehost").set_sensitive(False) + else: + self.glade.get_widget("button_connect").set_label("gtk-connect") + if status == HOSTLIST_STATUS.index("Offline") and not localhost: + self.glade.get_widget("button_connect").set_sensitive(False) + + # Check to see if the host is online + if status == HOSTLIST_STATUS.index("Connected") \ + or status == HOSTLIST_STATUS.index("Online"): + self.glade.get_widget("image_startdaemon").set_from_stock( + gtk.STOCK_STOP, gtk.ICON_SIZE_MENU) + self.glade.get_widget("label_startdaemon").set_text( + "_Stop Daemon") + + # Update the start daemon button if the selected host is localhost + if localhost and status == HOSTLIST_STATUS.index("Offline"): + # The localhost is not online + self.glade.get_widget("image_startdaemon").set_from_stock( + gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU) + self.glade.get_widget("label_startdaemon").set_text( + "_Start Daemon") + + if not localhost: + # An offline host + self.glade.get_widget("button_startdaemon").set_sensitive(False) + + # Make sure label is displayed correctly using mnemonics + self.glade.get_widget("label_startdaemon").set_use_underline( + True) + + def save(self): + """Save the current host list to file""" + def append_row(model=None, path=None, row=None, columns=None): + hostlist.append(model.get_value(row, HOSTLIST_COL_URI)) + + hostlist = [] + self.liststore.foreach(append_row, hostlist) + self.config["hosts"] = hostlist + self.config.save() + + def test_online_status(self, uri): + """Tests the status of URI.. Returns True or False depending on status. + """ + online = True + host = None + try: + host = xmlrpclib.ServerProxy(uri) + host.ping() + except socket.error: + online = False + + del host + self.online_status[uri] = online + return online + + ## Callbacks + def on_delete_event(self, widget, event): + self.hide() + return True + + def on_button_addhost_clicked(self, widget): + log.debug("on_button_addhost_clicked") + dialog = self.glade.get_widget("addhost_dialog") + dialog.set_icon(deluge.common.get_logo(16)) + hostname_entry = self.glade.get_widget("entry_hostname") + port_spinbutton = self.glade.get_widget("spinbutton_port") + response = dialog.run() + if response == 1: + # We add the host + self.add_host(hostname_entry.get_text(), + port_spinbutton.get_value_as_int()) + + dialog.hide() + + def add_host(self, hostname, port): + """Adds the host to the list""" + if hostname.startswith("http://"): + hostname = hostname[7:] + + # Check to make sure the hostname is at least 1 character long + if len(hostname) < 1: + return + + # Get the port and concatenate the hostname string + hostname = hostname + ":" + str(port) + + # Check to see if there is already an entry for this host and return + # if thats the case + self.hosts_liststore = [] + def each_row(model, path, iter, data): + self.hosts_liststore.append( + model.get_value(iter, HOSTLIST_COL_URI)) + self.liststore.foreach(each_row, None) + if hostname in self.hosts_liststore: + return + + # Host isn't in the list, so lets add it + row = self.liststore.append() + self.liststore.set_value(row, HOSTLIST_COL_URI, hostname) + # Save the host list to file + self.save() + # Update the status of the hosts + self._update_list() + + def on_button_removehost_clicked(self, widget): + log.debug("on_button_removehost_clicked") + # Get the selected rows + paths = self.hostlist.get_selection().get_selected_rows()[1] + for path in paths: + self.liststore.remove(self.liststore.get_iter(path)) + + # Update the hostlist + self._update_list() + + # Save the host list + self.save() + + def on_button_startdaemon_clicked(self, widget): + log.debug("on_button_startdaemon_clicked") + if self.liststore.iter_n_children(None) < 1: + # There is nothing in the list, so lets create a localhost entry + self.add_host("localhost", 58846) + # ..and start the daemon. + self.start_localhost(58846) + return + + paths = self.hostlist.get_selection().get_selected_rows()[1] + if len(paths) < 1: + return + row = self.liststore.get_iter(paths[0]) + status = self.liststore.get_value(row, HOSTLIST_COL_STATUS) + uri = self.liststore.get_value(row, HOSTLIST_COL_URI) + port = uri.split(":")[1] + if HOSTLIST_STATUS[status] == "Online" or\ + HOSTLIST_STATUS[status] == "Connected": + # We need to stop this daemon + uri = "http://" + uri + # Call the shutdown method on the daemon + core = xmlrpclib.ServerProxy(uri) + core.shutdown() + # Update display to show change + self.update() + elif HOSTLIST_STATUS[status] == "Offline": + self.start_localhost(port) + + def start_localhost(self, port): + """Starts a localhost daemon""" + port = str(port) + log.info("Starting localhost:%s daemon..", port) + # Spawn a local daemon + if deluge.common.windows_check(): + win32api.WinExec("deluged -p %s" % port) + else: + os.popen("deluged -p %s" % port) + + def on_button_close_clicked(self, widget): + log.debug("on_button_close_clicked") + self.hide() + + def on_button_connect_clicked(self, widget): + log.debug("on_button_connect_clicked") + paths = self.hostlist.get_selection().get_selected_rows()[1] + row = self.liststore.get_iter(paths[0]) + status = self.liststore.get_value(row, HOSTLIST_COL_STATUS) + uri = self.liststore.get_value(row, HOSTLIST_COL_URI) + # Determine if this is a localhost + localhost = False + port = uri.split(":")[1] + if uri.split(":")[0] == "localhost": + localhost = True + + uri = "http://" + uri + if status == HOSTLIST_STATUS.index("Connected"): + # Stop all the components first. + component.stop() + # If we are connected to this host, then we will disconnect. + client.set_core_uri(None) + self._update_list() + return + + # Test the host to see if it is online or not. We don't use the status + # column information because it can be up to 5 seconds out of sync. + if not self.test_online_status(uri): + log.warning("Host does not appear to be online..") + # If this is an offline localhost.. lets start it and connect + if localhost: + self.start_localhost(port) + # We need to wait for the host to start before connecting + while not self.test_online_status(uri): + time.sleep(0.01) + client.set_core_uri(uri) + self._update_list() + self.hide() + + # Update the list to show proper status + self._update_list() + + return + + # Status is OK, so lets change to this host + client.set_core_uri(uri) + self.hide() + + def on_chk_autoconnect_toggled(self, widget): + log.debug("on_chk_autoconnect_toggled") + value = widget.get_active() + self.gtkui_config["autoconnect"] = value + # If we are currently connected to a host, set that as the autoconnect + # host. + if client.get_core_uri() != None: + self.gtkui_config["autoconnect_host_uri"] = client.get_core_uri() + + def on_chk_autostart_toggled(self, widget): + log.debug("on_chk_autostart_toggled") + value = widget.get_active() + self.gtkui_config["autostart_localhost"] = value + + def on_chk_donotshow_toggled(self, widget): + log.debug("on_chk_donotshow_toggled") + value = widget.get_active() + self.gtkui_config["show_connection_manager_on_start"] = not value + + def on_selection_changed(self, treeselection): + log.debug("on_selection_changed") + self.update_buttons() diff --git a/deluge/ui/gtkui/coreconfig.py b/deluge/ui/gtkui/coreconfig.py new file mode 100644 index 000000000..ccb9658c7 --- /dev/null +++ b/deluge/ui/gtkui/coreconfig.py @@ -0,0 +1,63 @@ +# +# coreconfig.py +# +# Copyright (C) 2008 Andrew Resch ('andar') +# +# 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 2 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 deluge.component as component +from deluge.ui.client import aclient as client +from deluge.log import LOG as log + +class CoreConfig(component.Component): + def __init__(self): + log.debug("CoreConfig init..") + component.Component.__init__(self, "CoreConfig", ["Signals"]) + self.config = {} + component.get("Signals").connect_to_signal("config_value_changed", + self._on_config_value_changed) + + def start(self): + client.get_config(self._on_get_config) + + def stop(self): + self.config = {} + + def __getitem__(self, key): + return self.config[key] + + def __setitem__(self, key, value): + client.set_config({key: value}) + + def _on_get_config(self, config): + self.config = config + + def _on_config_value_changed(self, key, value): + self.config[key] = value + diff --git a/deluge/ui/gtkui/dbusinterface.py b/deluge/ui/gtkui/dbusinterface.py new file mode 100644 index 000000000..7ccc3b69b --- /dev/null +++ b/deluge/ui/gtkui/dbusinterface.py @@ -0,0 +1,92 @@ +# +# dbusinterface.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 + +# Import DBUS +import dbus, dbus.service + +if dbus.version >= (0,41,0) and dbus.version < (0,80,0): + import dbus.glib +elif dbus.version >= (0,80,0): + from dbus.mainloop.glib import DBusGMainLoop + DBusGMainLoop(set_as_default=True) + +import deluge.component as component +import deluge.common +from deluge.log import LOG as log + +class DbusInterface(dbus.service.Object, component.Component): + def __init__(self, args, path="/org/deluge_torrent/Deluge"): + component.Component.__init__(self, "DbusInterface") + # Check to see if the daemon is already running and if not, start it + bus = dbus.SessionBus() + obj = bus.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus") + iface = dbus.Interface(obj, "org.freedesktop.DBus") + if iface.NameHasOwner("org.deluge_torrent.Deluge"): + # Deluge client already running.. Lets exit. + log.info("Deluge already running..") + log.debug("args: %s", args) + # Convert the paths to absolutes + new_args = [] + for arg in args: + if not deluge.common.is_url(arg): + new_args.append(os.path.abspath(arg)) + args = new_args + + # Send the args to the running session + if args != [] and args != None: + bus = dbus.SessionBus() + proxy = bus.get_object("org.deluge_torrent.Deluge", + "/org/deluge_torrent/Deluge") + ui = dbus.Interface(proxy, "org.deluge_torrent.Deluge") + ui.process_args(args) + # Exit + log.debug("Exiting..") + sys.exit(0) + + # Process the args if any + self.process_args(args) + # Register Deluge with Dbus + log.info("Registering with DBUS..") + bus_name = dbus.service.BusName("org.deluge_torrent.Deluge", + bus=dbus.SessionBus()) + dbus.service.Object.__init__(self, bus_name, path) + + @dbus.service.method("org.deluge_torrent.Deluge", in_signature="as") + def process_args(self, args): + """Process arguments sent to already running Deluge""" + from ipcinterface import process_args + process_args(args) + diff --git a/deluge/ui/gtkui/details_tab.py b/deluge/ui/gtkui/details_tab.py new file mode 100644 index 000000000..d48e2c68e --- /dev/null +++ b/deluge/ui/gtkui/details_tab.py @@ -0,0 +1,108 @@ +# +# details_tab.py +# +# Copyright (C) 2008 Andrew Resch ('andar') +# +# 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 2 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, gtk.glade + +from deluge.ui.client import aclient as client +import deluge.component as component +import deluge.common +from deluge.ui.gtkui.torrentdetails import Tab + +from deluge.log import LOG as log + +class DetailsTab(Tab): + def __init__(self): + # Get the labels we need to update. + # widgetname, modifier function, status keys + glade = component.get("MainWindow").main_glade + + self._name = "Details" + self._child_widget = glade.get_widget("details_tab") + self._tab_label = glade.get_widget("details_tab_label") + + self.label_widgets = [ + (glade.get_widget("summary_name"), None, ("name",)), + (glade.get_widget("summary_total_size"), deluge.common.fsize, ("total_size",)), + (glade.get_widget("summary_num_files"), str, ("num_files",)), + (glade.get_widget("summary_tracker"), None, ("tracker",)), + (glade.get_widget("summary_torrent_path"), None, ("save_path",)), + (glade.get_widget("summary_message"), str, ("message",)), + (glade.get_widget("summary_hash"), str, ("hash",)) + ] + + def update(self): + # Get the first selected torrent + selected = component.get("TorrentView").get_selected_torrents() + + # Only use the first torrent in the list or return if None selected + if len(selected) != 0: + selected = selected[0] + else: + # No torrent is selected in the torrentview + self.clear() + return + + # Get the torrent status + status_keys = ["name", "total_size", "num_files", + "tracker", "save_path", "message", "hash"] + + client.get_torrent_status( + self._on_get_torrent_status, selected, status_keys) + + def _on_get_torrent_status(self, status): + # Check to see if we got valid data from the core + if status is None: + return + + # Update all the label widgets + for widget in self.label_widgets: + if widget[1] != None: + args = [] + try: + for key in widget[2]: + args.append(status[key]) + except Exception, e: + log.debug("Unable to get status value: %s", e) + continue + + txt = widget[1](*args) + else: + txt = status[widget[2][0]] + + if widget[0].get_text() != txt: + widget[0].set_text(txt) + + def clear(self): + for widget in self.label_widgets: + widget[0].set_text("") + diff --git a/deluge/ui/gtkui/edittrackersdialog.py b/deluge/ui/gtkui/edittrackersdialog.py new file mode 100644 index 000000000..64c2730a0 --- /dev/null +++ b/deluge/ui/gtkui/edittrackersdialog.py @@ -0,0 +1,200 @@ +# +# edittrackersdialog.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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, gtk.glade +import pkg_resources + +import deluge.common +from deluge.ui.client import aclient as client +import deluge.component as component +from deluge.log import LOG as log + +class EditTrackersDialog: + def __init__(self, torrent_id, parent=None): + self.torrent_id = torrent_id + self.glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/edit_trackers.glade")) + + self.dialog = self.glade.get_widget("edit_trackers_dialog") + self.treeview = self.glade.get_widget("tracker_treeview") + self.add_tracker_dialog = self.glade.get_widget("add_tracker_dialog") + self.add_tracker_dialog.set_transient_for(self.dialog) + + self.dialog.set_icon(deluge.common.get_logo(32)) + + if parent != None: + self.dialog.set_transient_for(parent) + + # Connect the signals + self.glade.signal_autoconnect({ + "on_button_up_clicked": self.on_button_up_clicked, + "on_button_add_clicked": self.on_button_add_clicked, + "on_button_remove_clicked": self.on_button_remove_clicked, + "on_button_down_clicked": self.on_button_down_clicked, + "on_button_ok_clicked": self.on_button_ok_clicked, + "on_button_cancel_clicked": self.on_button_cancel_clicked, + "on_button_add_ok_clicked": self.on_button_add_ok_clicked, + "on_button_add_cancel_clicked": self.on_button_add_cancel_clicked + }) + + # Create a liststore for tier, url + self.liststore = gtk.ListStore(int, str) + + # Create the columns + self.treeview.append_column( + gtk.TreeViewColumn(_("Tier"), gtk.CellRendererText(), text=0)) + self.treeview.append_column( + gtk.TreeViewColumn(_("Tracker"), gtk.CellRendererText(), text=1)) + + self.treeview.set_model(self.liststore) + self.liststore.set_sort_column_id(0, gtk.SORT_ASCENDING) + + def run(self): + # Make sure we have a torrent_id.. if not just return + if self.torrent_id == None: + return + + # Get the trackers for this torrent + + client.get_torrent_status( + self._on_get_torrent_status, self.torrent_id, ["trackers"]) + client.force_call() + + def _on_get_torrent_status(self, status): + """Display trackers dialog""" + for tracker in status["trackers"]: + self.add_tracker(tracker["tier"], tracker["url"]) + + self.dialog.show() + + def add_tracker(self, tier, url): + """Adds a tracker to the list""" + self.liststore.append([tier, url]) + + def get_selected(self): + """Returns the selected tracker""" + return self.treeview.get_selection().get_selected()[1] + + def on_button_up_clicked(self, widget): + log.debug("on_button_up_clicked") + selected = self.get_selected() + num_rows = self.liststore.iter_n_children(None) + if selected != None and num_rows > 1: + tier = self.liststore.get_value(selected, 0) + new_tier = tier + 1 + # Now change the tier for this tracker + self.liststore.set_value(selected, 0, new_tier) + + def on_button_add_clicked(self, widget): + log.debug("on_button_add_clicked") + # Show the add tracker dialog + self.add_tracker_dialog.show() + self.glade.get_widget("entry_tracker").grab_focus() + + def on_button_remove_clicked(self, widget): + log.debug("on_button_remove_clicked") + selected = self.get_selected() + if selected != None: + self.liststore.remove(selected) + + def on_button_down_clicked(self, widget): + log.debug("on_button_down_clicked") + selected = self.get_selected() + num_rows = self.liststore.iter_n_children(None) + if selected != None and num_rows > 1: + tier = self.liststore.get_value(selected, 0) + if not tier > 0: + return + new_tier = tier - 1 + # Now change the tier for this tracker + self.liststore.set_value(selected, 0, new_tier) + + def on_button_ok_clicked(self, widget): + log.debug("on_button_ok_clicked") + self.trackers = [] + def each(model, path, iter, data): + tracker = {} + tracker["tier"] = model.get_value(iter, 0) + tracker["url"] = model.get_value(iter, 1) + self.trackers.append(tracker) + self.liststore.foreach(each, None) + # Set the torrens trackers + client.set_torrent_trackers(self.torrent_id, self.trackers) + self.dialog.destroy() + + def on_button_cancel_clicked(self, widget): + log.debug("on_button_cancel_clicked") + self.dialog.destroy() + + def on_button_add_ok_clicked(self, widget): + log.debug("on_button_add_ok_clicked") + from re import search as re_search + tracker = self.glade.get_widget("entry_tracker").get_text() + if not re_search("[udp|http]s?://", tracker): + # Bad url.. lets prepend http:// + tracker = "http://" + tracker + + # Figure out what tier number to use.. it's going to be the highest+1 + # Also check for duplicates + self.highest_tier = 0 + self.duplicate = False + def tier_count(model, path, iter, data): + tier = model.get_value(iter, 0) + if tier > self.highest_tier: + self.highest_tier = tier + tracker = model.get_value(iter, 1) + if data == tracker: + # We already have this tracker in the list + self.duplicate = True + + # Check if there are any entries + if self.liststore.iter_n_children(None) > 0: + self.liststore.foreach(tier_count, tracker) + else: + self.highest_tier = -1 + + # If not a duplicate, then add it to the list + if not self.duplicate: + # Add the tracker to the list + self.add_tracker(self.highest_tier + 1, tracker) + + # Clear the entry widget and hide the dialog + self.glade.get_widget("entry_tracker").set_text("") + self.add_tracker_dialog.hide() + + def on_button_add_cancel_clicked(self, widget): + log.debug("on_button_add_cancel_clicked") + # Clear the entry widget and hide the dialog + self.glade.get_widget("entry_tracker").set_text("") + self.add_tracker_dialog.hide() diff --git a/deluge/ui/gtkui/files_tab.py b/deluge/ui/gtkui/files_tab.py new file mode 100644 index 000000000..dd9c29ea6 --- /dev/null +++ b/deluge/ui/gtkui/files_tab.py @@ -0,0 +1,425 @@ +# +# files_tab.py +# +# Copyright (C) 2008 Andrew Resch ('andar') +# +# 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 2 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, gtk.glade +import gobject +import gettext +import os.path +import cPickle + +from deluge.ui.gtkui.torrentdetails import Tab +from deluge.ui.client import aclient as client +from deluge.configmanager import ConfigManager +import deluge.component as component +import deluge.common + +from deluge.log import LOG as log + +def cell_priority(column, cell, model, row, data): + if model.get_value(row, 5) == -1: + # This is a folder, so lets just set it blank for now + cell.set_property("text", "") + return + priority = model.get_value(row, data) + cell.set_property("text", deluge.common.FILE_PRIORITY[priority]) + +def cell_priority_icon(column, cell, model, row, data): + if model.get_value(row, 5) == -1: + # This is a folder, so lets just set it blank for now + cell.set_property("stock-id", None) + return + priority = model.get_value(row, data) + if deluge.common.FILE_PRIORITY[priority] == "Do Not Download": + cell.set_property("stock-id", gtk.STOCK_STOP) + elif deluge.common.FILE_PRIORITY[priority] == "Normal Priority": + cell.set_property("stock-id", gtk.STOCK_YES) + elif deluge.common.FILE_PRIORITY[priority] == "High Priority": + cell.set_property("stock-id", gtk.STOCK_GO_UP) + elif deluge.common.FILE_PRIORITY[priority] == "Highest Priority": + cell.set_property("stock-id", gtk.STOCK_GOTO_TOP) + +def cell_filename(column, cell, model, row, data): + """Only show the tail portion of the file path""" + filepath = model.get_value(row, data) + cell.set_property("text", os.path.split(filepath)[1]) + +def cell_progress(column, cell, model, row, data): + if model.get_value(row, 5) == -1: + # This is a folder, so lets just set it blank for now + cell.set_property("visible", False) + return + text = model.get_value(row, data[0]) + value = model.get_value(row, data[1]) + cell.set_property("visible", True) + cell.set_property("text", text) + cell.set_property("value", value) + +class ColumnState: + def __init__(self, name, position, width, sort, sort_order): + self.name = name + self.position = position + self.width = width + self.sort = sort + self.sort_order = sort_order + +class FilesTab(Tab): + def __init__(self): + glade = component.get("MainWindow").get_glade() + + self._name = "Files" + self._child_widget = glade.get_widget("files_tab") + self._tab_label = glade.get_widget("files_tab_label") + + self.listview = glade.get_widget("files_listview") + # filename, size, progress string, progress value, priority, file index, icon id + self.treestore = gtk.TreeStore(str, gobject.TYPE_UINT64, str, int, int, int, str) + + # Filename column + column = gtk.TreeViewColumn(_("Filename")) + render = gtk.CellRendererPixbuf() + column.pack_start(render, False) + column.add_attribute(render, "stock-id", 6) + render = gtk.CellRendererText() + column.pack_start(render, True) + column.add_attribute(render, "text", 0) + column.set_sort_column_id(0) + column.set_clickable(True) + column.set_resizable(True) + column.set_expand(False) + column.set_min_width(10) + column.set_reorderable(True) + self.listview.append_column(column) + + # Size column + column = gtk.TreeViewColumn(_("Size")) + render = gtk.CellRendererText() + column.pack_start(render, False) + column.set_cell_data_func(render, deluge.ui.gtkui.listview.cell_data_size, 1) + column.set_sort_column_id(1) + column.set_clickable(True) + column.set_resizable(True) + column.set_expand(False) + column.set_min_width(10) + column.set_reorderable(True) + self.listview.append_column(column) + + # Progress column + column = gtk.TreeViewColumn(_("Progress")) + render = gtk.CellRendererProgress() + column.pack_start(render) + column.set_cell_data_func(render, cell_progress, (2, 3)) + column.set_sort_column_id(3) + column.set_clickable(True) + column.set_resizable(True) + column.set_expand(False) + column.set_min_width(10) + column.set_reorderable(True) + self.listview.append_column(column) + + # Priority column + column = gtk.TreeViewColumn(_("Priority")) + render = gtk.CellRendererPixbuf() + column.pack_start(render, False) + column.set_cell_data_func(render, cell_priority_icon, 4) + render = gtk.CellRendererText() + column.pack_start(render, False) + column.set_cell_data_func(render, cell_priority, 4) + column.set_sort_column_id(4) + column.set_clickable(True) + column.set_resizable(True) + column.set_expand(False) + column.set_min_width(10) + column.set_reorderable(True) + self.listview.append_column(column) + + self.listview.set_model(self.treestore) + + self.listview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) + + self.file_menu = glade.get_widget("menu_file_tab") + self.listview.connect("row-activated", self._on_row_activated) + self.listview.connect("button-press-event", self._on_button_press_event) + + glade.signal_autoconnect({ + "on_menuitem_open_file_activate": self._on_menuitem_open_file_activate, + "on_menuitem_donotdownload_activate": self._on_menuitem_donotdownload_activate, + "on_menuitem_normal_activate": self._on_menuitem_normal_activate, + "on_menuitem_high_activate": self._on_menuitem_high_activate, + "on_menuitem_highest_activate": self._on_menuitem_highest_activate, + "on_menuitem_expand_all_activate": self._on_menuitem_expand_all_activate + }) + + # Attempt to load state + self.load_state() + + # torrent_id: (filepath, size) + self.files_list = {} + + self.torrent_id = None + + def save_state(self): + filename = "files_tab.state" + state = [] + for index, column in enumerate(self.listview.get_columns()): + state.append(ColumnState(column.get_title(), index, column.get_width(), + column.get_sort_indicator(), int(column.get_sort_order()))) + + # Get the config location for saving the state file + config_location = ConfigManager("gtkui.conf")["config_location"] + + try: + log.debug("Saving FilesTab state file: %s", filename) + state_file = open(os.path.join(config_location, filename), "wb") + cPickle.dump(state, state_file) + state_file.close() + except IOError, e: + log.warning("Unable to save state file: %s", e) + + def load_state(self): + filename = "files_tab.state" + # Get the config location for loading the state file + config_location = ConfigManager("gtkui.conf")["config_location"] + state = None + + try: + log.debug("Loading FilesTab state file: %s", filename) + state_file = open(os.path.join(config_location, filename), "rb") + state = cPickle.load(state_file) + state_file.close() + except (EOFError, IOError), e: + log.warning("Unable to load state file: %s", e) + + if state == None: + return + + for column_state in state: + # Find matching columns in the listview + for (index, column) in enumerate(self.listview.get_columns()): + if column_state.name == column.get_title(): + # We have a match, so set options that were saved in state + if column_state.width > 0: + column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + column.set_fixed_width(column_state.width) + column.set_sort_indicator(column_state.sort) + column.set_sort_order(column_state.sort_order) + if column_state.position != index: + # Column is in wrong position + if column_state.position == 0: + self.listview.move_column_after(column, None) + else: + self.listview.move_column_after(column, self.listview.get_columns()[column_state.position - 1]) + + def update(self): + # Get the first selected torrent + torrent_id = component.get("TorrentView").get_selected_torrents() + + # Only use the first torrent in the list or return if None selected + if len(torrent_id) != 0: + torrent_id = torrent_id[0] + else: + # No torrent is selected in the torrentview + self.treestore.clear() + return + + if torrent_id != self.torrent_id: + # We only want to do this if the torrent_id has changed + self.treestore.clear() + self.torrent_id = torrent_id + + if self.torrent_id not in self.files_list.keys(): + # We need to get the files list + log.debug("Getting file list from core..") + client.get_torrent_status( + self._on_get_torrent_files, + self.torrent_id, + ["files", "file_progress", "file_priorities"]) + client.force_call(block=True) + else: + self.update_files() + client.get_torrent_status(self._on_get_torrent_status, self.torrent_id, ["file_progress", "file_priorities"]) + client.force_call(True) + else: + client.get_torrent_status(self._on_get_torrent_status, self.torrent_id, ["file_progress", "file_priorities"]) + client.force_call(True) + + def clear(self): + self.treestore.clear() + + def _on_row_activated(self, tree, path, view_column): + if client.is_localhost: + client.get_torrent_status(self._on_open_file, self.torrent_id, ["save_path", "files"]) + client.force_call(False) + + def get_file_path(self, row, path=""): + if not row: + return path + + path = self.treestore.get_value(row, 0) + path + return self.get_file_path(self.treestore.iter_parent(row), path) + + def _on_open_file(self, status): + paths = self.listview.get_selection().get_selected_rows()[1] + selected = [] + for path in paths: + selected.append(self.treestore.get_iter(path)) + + for select in selected: + path = self.get_file_path(select).split("/") + filepath = os.path.join(status["save_path"], *path) + log.debug("Open file '%s'", filepath) + deluge.common.open_file(filepath) + + ## The following 3 methods create the folder/file view in the treeview + def prepare_file_store(self, files): + split_files = { } + i = 0 + for file in files: + self.prepare_file(file, file["path"], i, split_files) + i += 1 + self.add_files(None, split_files) + + def prepare_file(self, file, file_name, file_num, files_storage): + first_slash_index = file_name.find("/") + if first_slash_index == -1: + files_storage[file_name] = (file_num, file) + else: + file_name_chunk = file_name[:first_slash_index+1] + if file_name_chunk not in files_storage: + files_storage[file_name_chunk] = { } + self.prepare_file(file, file_name[first_slash_index+1:], + file_num, files_storage[file_name_chunk]) + + def add_files(self, parent_iter, split_files): + ret = 0 + for key,value in split_files.iteritems(): + if key.endswith("/"): + chunk_iter = self.treestore.append(parent_iter, + [key, 0, "", 0, 0, -1, gtk.STOCK_DIRECTORY]) + chunk_size = self.add_files(chunk_iter, value) + self.treestore.set(chunk_iter, 1, chunk_size) + ret += chunk_size + else: + self.treestore.append(parent_iter, [key, + value[1]["size"], "", 0, 0, value[0], gtk.STOCK_FILE]) + ret += value[1]["size"] + return ret + ### + + def update_files(self): + self.prepare_file_store(self.files_list[self.torrent_id]) + + def get_selected_files(self): + """Returns a list of file indexes that are selected""" + selected = [] + paths = self.listview.get_selection().get_selected_rows()[1] + for path in paths: + selected.append(self.treestore.get_value(self.treestore.get_iter(path), 5)) + + return selected + + def _on_get_torrent_files(self, status): + self.files_list[self.torrent_id] = status["files"] + self.update_files() + self._on_get_torrent_status(status) + + def get_files_from_tree(self, rows, files_list, indent): + if not rows: + return None + + for row in rows: + if row[5] > -1: + files_list.append((row[5], row)) + self.get_files_from_tree(row.iterchildren(), files_list, indent+1) + return None + + def _on_get_torrent_status(self, status): + # (index, iter) + files_list = [] + self.get_files_from_tree(self.treestore, files_list, 0) + files_list.sort() + for index, row in files_list: + row[2] = "%.2f%%" % (status["file_progress"][index] * 100) + row[3] = status["file_progress"][index] * 100 + row[4] = status["file_priorities"][index] + + def _on_button_press_event(self, widget, event): + """This is a callback for showing the right-click context menu.""" + log.debug("on_button_press_event") + # We only care about right-clicks + if self.get_selected_files() and event.button == 3: + self.file_menu.popup(None, None, None, event.button, event.time) + return True + + def _on_menuitem_open_file_activate(self, menuitem): + self._on_row_activated(None, None, None) + + def _set_file_priorities_on_user_change(self, selected, priority): + """Sets the file priorities in the core. It will change the selected + with the 'priority'""" + file_priorities = [] + def set_file_priority(model, path, iter, data): + index = model.get_value(iter, 5) + if index in selected: + file_priorities.append((index, priority)) + elif index != -1: + file_priorities.append((index, model.get_value(iter, 4))) + + self.treestore.foreach(set_file_priority, None) + file_priorities.sort() + priorities = [p[1] for p in file_priorities] + log.debug("priorities: %s", priorities) + + client.set_torrent_file_priorities(self.torrent_id, priorities) + + def _on_menuitem_donotdownload_activate(self, menuitem): + self._set_file_priorities_on_user_change( + self.get_selected_files(), + deluge.common.FILE_PRIORITY["Do Not Download"]) + + def _on_menuitem_normal_activate(self, menuitem): + self._set_file_priorities_on_user_change( + self.get_selected_files(), + deluge.common.FILE_PRIORITY["Normal Priority"]) + + def _on_menuitem_high_activate(self, menuitem): + self._set_file_priorities_on_user_change( + self.get_selected_files(), + deluge.common.FILE_PRIORITY["High Priority"]) + + def _on_menuitem_highest_activate(self, menuitem): + self._set_file_priorities_on_user_change( + self.get_selected_files(), + deluge.common.FILE_PRIORITY["Highest Priority"]) + + def _on_menuitem_expand_all_activate(self, menuitem): + self.listview.expand_all() diff --git a/deluge/ui/gtkui/glade/add_torrent_dialog.glade b/deluge/ui/gtkui/glade/add_torrent_dialog.glade new file mode 100644 index 000000000..f954ca0a6 --- /dev/null +++ b/deluge/ui/gtkui/glade/add_torrent_dialog.glade @@ -0,0 +1,1187 @@ + + + + + + 560 + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Add Torrents + GTK_WIN_POS_CENTER_ON_PARENT + True + GDK_WINDOW_TYPE_HINT_DIALOG + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-add + 5 + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <big><b>Add Torrents</b></big> + True + + + False + False + 1 + + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 12 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + + + 100 + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_CENTER + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + 4 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-open + 1 + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + From _File + True + + + False + False + 1 + + + + + + + False + False + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + 4 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-network + 1 + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + From _URL + True + + + False + False + 1 + + + + + + + False + False + 1 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + 4 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-revert-to-saved + 1 + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + From _Hash + True + + + False + False + 1 + + + + + + + False + False + 2 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 4 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-remove + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Remove + True + + + False + False + 1 + + + + + + + False + False + 3 + + + + + False + False + 1 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Torrents</b> + True + + + label_item + + + + + False + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_OUT + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-open + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Fi_les + True + + + 5 + 1 + + + + + tab + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 5 + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER + Select A Folder + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + 1 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Download Location</b> + True + + + label_item + + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Full + 0 + True + True + + + False + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Compact + 0 + True + True + radio_full + + + False + False + 1 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Allocation</b> + True + + + label_item + + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 4 + 2 + 10 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + -1 -1 9999 1 10 10 + + + 1 + 2 + 3 + 4 + + + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + -1 -1 9999 1 10 10 + + + 1 + 2 + 2 + 3 + + + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + -1 -1 9999 1 10 10 + GTK_UPDATE_IF_VALID + + + 1 + 2 + 1 + 2 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Max Upload Slots: + + + 3 + 4 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Max Connections: + + + 2 + 3 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Max Up Speed: + + + 1 + 2 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Max Down Speed: + + + GTK_FILL + + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + -1 -1 9999 1 10 10 + + + 1 + 2 + + + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Bandwidth</b> + True + + + label_item + + + + + False + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Add In _Paused State + True + 0 + True + + + False + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Prioritize First/Last Pieces + 0 + True + + + False + False + 1 + + + + + True + False + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Private + 0 + True + + + False + False + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_START + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-edit + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Edit Trackers + True + + + False + False + 5 + 1 + + + + + + + False + False + + + + + False + False + 3 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>General</b> + True + + + label_item + + + + + False + False + 2 + + + + + False + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-revert-to-saved + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Revert To Defaults + + + False + False + 5 + 1 + + + + + + + + + False + False + GTK_PACK_END + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + gtk-apply + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Apply To All + + + False + False + 5 + 1 + + + + + + + + + False + False + GTK_PACK_END + + + + + False + False + 2 + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-properties + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Options + True + + + 5 + 1 + + + + + tab + 1 + False + + + + + True + True + + + + + 2 + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + 0 + + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-add + True + 0 + + + + 1 + + + + + False + GTK_PACK_END + + + + + + + 462 + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Add Tracker + GTK_WIN_POS_CENTER_ON_PARENT + True + GDK_WINDOW_TYPE_HINT_DIALOG + False + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-add + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>From URL</b> + True + + + False + False + 1 + + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + URL: + + + False + False + + + + + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + 1 + + + + + False + False + 2 + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + -6 + + + + + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-ok + True + -5 + + + 1 + + + + + False + GTK_PACK_END + + + + + + diff --git a/deluge/ui/gtkui/glade/connection_manager.glade b/deluge/ui/gtkui/glade/connection_manager.glade new file mode 100644 index 000000000..237ff9b98 --- /dev/null +++ b/deluge/ui/gtkui/glade/connection_manager.glade @@ -0,0 +1,422 @@ + + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Connection Manager + GTK_WIN_POS_CENTER_ON_PARENT + 350 + 300 + True + GDK_WINDOW_TYPE_HINT_DIALOG + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-missing-image + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <big><b>Connection Manager</b></big> + True + + + False + 1 + + + + + False + 5 + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_START + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-add + True + 0 + + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-remove + True + 0 + + + + 1 + + + + + False + False + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-execute + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Start local daemon + True + + + 1 + + + + + + + False + False + GTK_PACK_END + 1 + + + + + False + False + 1 + + + + + 10 + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 5 + 5 + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Automatically connect to selected host on start-up + 0 + True + + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Automatically start localhost if needed + 0 + True + + + + 1 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Do not show this dialog on start-up + 0 + True + + + + 2 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Options + + + label_item + + + + + False + 3 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-close + True + 0 + + + + False + False + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-connect + True + 0 + + + + False + False + 1 + + + + + False + GTK_PACK_END + + + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Add Host + GTK_WIN_POS_CENTER + True + GDK_WINDOW_TYPE_HINT_DIALOG + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Hostname: + + + False + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Port: + + + False + False + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 5 + 1 + 58846 1 65535 1 10 10 + True + + + False + False + 3 + + + + + False + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + 0 + + + + + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-add + True + 1 + + + 1 + + + + + False + GTK_PACK_END + + + + + + diff --git a/plugins/MoveTorrent/movetorrent.glade b/deluge/ui/gtkui/glade/dgtkpopups.glade similarity index 64% rename from plugins/MoveTorrent/movetorrent.glade rename to deluge/ui/gtkui/glade/dgtkpopups.glade index 5bef94375..249640db1 100644 --- a/plugins/MoveTorrent/movetorrent.glade +++ b/deluge/ui/gtkui/glade/dgtkpopups.glade @@ -1,77 +1,89 @@ - + - + + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 5 - GTK_WIN_POS_CENTER_ON_PARENT - GDK_WINDOW_TYPE_HINT_DIALOG + Speed + GTK_WIN_POS_MOUSE + True + GDK_WINDOW_TYPE_HINT_NORMAL + True + True + False False - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 2 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Move completed downloads to: - 0 - True - - - - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER - Select A Folder + False + + + + + True + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + 1 + 0 -1 10000 1 10 10 + True + + + False + False 1 - False False 1 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK GTK_BUTTONBOX_END - + True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-cancel + gtk-cancel True 0 - - + True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-ok + gtk-ok True - 0 - + 1 1 diff --git a/deluge/ui/gtkui/glade/edit_trackers.glade b/deluge/ui/gtkui/glade/edit_trackers.glade new file mode 100644 index 000000000..9e6fc8f71 --- /dev/null +++ b/deluge/ui/gtkui/glade/edit_trackers.glade @@ -0,0 +1,352 @@ + + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Edit Trackers + GTK_WIN_POS_CENTER_ON_PARENT + 400 + True + GDK_WINDOW_TYPE_HINT_DIALOG + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-edit + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0.05000000074505806 + 10 + <big><b>Edit Trackers</b></big> + True + + + False + False + 1 + + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + GTK_BUTTONBOX_CENTER + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-go-up + True + 0 + + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-add + True + 0 + + + + 1 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-remove + True + 0 + + + + 2 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-go-down + True + 0 + + + + 3 + + + + + False + False + 1 + + + + + 1 + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + 0 + + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-ok + True + 0 + + + + 1 + + + + + False + GTK_PACK_END + + + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Add Tracker + GTK_WIN_POS_CENTER_ON_PARENT + True + GDK_WINDOW_TYPE_HINT_DIALOG + False + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-add + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Add Tracker</b> + True + + + False + False + 1 + + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Tracker: + + + False + False + + + + + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + 1 + + + + + False + False + 2 + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + 0 + + + + + + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-ok + True + 0 + + + + 1 + + + + + False + GTK_PACK_END + + + + + + diff --git a/deluge/ui/gtkui/glade/file_tab_menu.glade b/deluge/ui/gtkui/glade/file_tab_menu.glade new file mode 100644 index 000000000..8e3f34162 --- /dev/null +++ b/deluge/ui/gtkui/glade/file_tab_menu.glade @@ -0,0 +1,100 @@ + + + + + + + True + + + + True + Select All + True + + + + + True + gtk-select-all + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Unselect All + True + + + + + True + gtk-file + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + Check Selected + True + + + + + True + gtk-ok + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Uncheck Selected + True + + + + + True + gtk-remove + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + diff --git a/deluge/ui/gtkui/glade/main_window.glade b/deluge/ui/gtkui/glade/main_window.glade new file mode 100644 index 000000000..e00555ebb --- /dev/null +++ b/deluge/ui/gtkui/glade/main_window.glade @@ -0,0 +1,2478 @@ + + + + + + Deluge + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + + + True + _File + True + + + + + True + False + _Add Torrent + True + + + + True + gtk-add + 1 + + + + + + + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Quit & Shutdown Daemon + True + + + + gtk-quit + 1 + + + + + + + True + + + + + True + gtk-quit + True + True + + + + + + + + + + True + _Edit + True + + + True + + + True + gtk-preferences + True + True + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Connection Manager + True + + + + gtk-network + 1 + + + + + + + + + + + _Torrent + True + + + + + True + _View + True + + + True + + + True + _Toolbar + True + True + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Labels + True + True + + + + + + True + Status_bar + True + True + + + + + + True + + + + + True + T_abs + True + + + + + True + _Columns + True + + + + + + + + + True + _Help + True + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Homepage + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-home + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Frequently Asked Questions + FAQ + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-dialog-question + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Community + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-info + 1 + + + + + + + True + + + + + True + gtk-about + True + True + + + + + + + + + + False + + + + + True + GTK_TOOLBAR_ICONS + GTK_ICON_SIZE_SMALL_TOOLBAR + + + True + False + Add torrent + Add Torrent + True + gtk-add + + + + False + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Remove Torrent + gtk-remove + + + + False + False + + + + + True + + + False + False + + + + + True + False + Pause the selected torrents + Pause + True + gtk-media-pause + + + + False + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Resume the selected torrents + Resume + gtk-media-play + + + + False + False + + + + + True + + + False + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Queue Torrent Up + Queue Up + gtk-go-up + + + + False + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Queue Torrent Down + Queue Down + gtk-go-down + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + False + + + + + True + Preferences + Preferences + True + gtk-preferences + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Connection Manager + Connection Manager + gtk-network + + + + False + False + + + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + 110 + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_OUT + + + True + True + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + False + + + + + False + False + + + + + True + False + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_OUT + + + True + True + True + True + True + False + + + + + True + False + + + + + True + False + + + + + True + False + + + False + False + + + + + + + 2 + + + + + True + + + False + 3 + + + + + + + True + + + True + gtk-open + True + True + + + + + + True + + + + + True + _Expand All + True + + + + True + gtk-zoom-in + 1 + + + + + + + True + + + + + True + _Do Not Download + True + + + + True + gtk-stop + 1 + + + + + + + True + _Normal Priority + True + + + + True + gtk-yes + 1 + + + + + + + True + _High Priority + True + + + + True + gtk-go-up + 1 + + + + + + + True + Hi_ghest Priority + True + + + + True + gtk-goto-top + 1 + + + + + + + + + True + True + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_NEVER + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + 10 + 10 + 15 + 15 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + True + 0.10000000149 + + + False + False + + + + + True + 5 + 8 + 15 + 5 + + + + + + + + + + + + + + + True + + + 5 + 6 + 3 + 4 + GTK_FILL + + + + + True + 0 + <b>Auto Managed:</b> + True + + + 4 + 5 + 3 + 4 + GTK_FILL + + + + + True + + + 7 + 8 + 2 + 3 + GTK_FILL + + + + + True + + + 7 + 8 + 1 + 2 + GTK_FILL + + + + + True + 0 + <b>Seed Rank:</b> + True + + + 6 + 7 + 2 + 3 + GTK_FILL + + + + + True + 0 + <b>Seeding Time:</b> + True + + + 6 + 7 + 1 + 2 + GTK_FILL + + + + + True + + + 7 + 8 + GTK_FILL + + + + + True + 0 + <b>Active Time:</b> + True + + + 6 + 7 + GTK_FILL + + + + + True + 0 + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + 0 + + + 3 + 4 + 3 + 4 + GTK_FILL + + + + + True + 0 + PANGO_WRAP_CHAR + True + + + 1 + 6 + 4 + 5 + GTK_FILL + + + + + True + 0 + <b>Tracker Status:</b> + True + + + 4 + 5 + GTK_FILL + + + + + + True + 0 + True + PANGO_WRAP_WORD_CHAR + + + 5 + 6 + 2 + 3 + GTK_FILL + + + + + + True + 0 + 1 + <b>Availability:</b> + True + + + 4 + 5 + 2 + 3 + GTK_FILL + + + + + True + 0 + + + 3 + 4 + 2 + 3 + GTK_FILL + + + + + True + 0 + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + 0 + + + 5 + 6 + 1 + 2 + GTK_FILL + + + + + True + 0 + <b>Peers:</b> + True + + + 4 + 5 + 1 + 2 + GTK_FILL + + + + + True + 0 + + + 5 + 6 + GTK_FILL + + + + + True + 0 + <b>Seeders:</b> + True + + + 4 + 5 + GTK_FILL + + + + + True + 15 + 5 + + + True + 0 + <b>Pieces:</b> + True + + + + + 2 + 3 + 3 + 4 + GTK_FILL + + + + + True + 15 + 5 + + + True + 0 + <b>ETA:</b> + True + + + + + 2 + 3 + 2 + 3 + GTK_FILL + + + + + True + 15 + 5 + + + True + 0 + <b>Speed:</b> + True + + + + + 2 + 3 + 1 + 2 + GTK_FILL + + + + + True + 15 + 5 + + + True + 0 + <b>Speed:</b> + True + + + + + 2 + 3 + GTK_FILL + + + + + True + 5 + + + True + 0 + <b>Next Announce:</b> + True + + + + + 3 + 4 + GTK_FILL + + + + + True + 5 + + + True + 0 + <b>Share Ratio:</b> + True + + + + + 2 + 3 + GTK_FILL + + + + + True + 5 + + + True + 0 + <b>Uploaded:</b> + True + + + + + 1 + 2 + GTK_FILL + + + + + True + 5 + + + True + 0 + <b>Downloaded:</b> + True + + + + + GTK_FILL + + + + + True + 0 + + + 3 + 4 + 1 + 2 + GTK_FILL + + + + + True + 0 + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + 0 + + + 3 + 4 + GTK_FILL + + + + + True + 0 + + + 1 + 2 + GTK_FILL + + + + + False + 1 + + + + + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-dialog-info + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Statistics + True + + + 1 + + + + + tab + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + 10 + 15 + 15 + + + True + 7 + 4 + 2 + + + + + + + + + + + + + + + True + 0 + True + + + 1 + 2 + 4 + 5 + + + + + + True + 0 + 1 + <b># of files:</b> + True + + + 4 + 5 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + True + PANGO_WRAP_CHAR + True + + + 1 + 4 + 1 + 2 + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <b>Hash:</b> + True + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + True + + + 1 + 4 + 6 + 7 + + + + + + True + 0 + 1 + <b>Tracker:</b> + True + + + 6 + 7 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + 0 + 1 + <b>Total Size:</b> + True + + + + + 3 + 4 + GTK_FILL + + + + + + True + 0 + True + PANGO_WRAP_CHAR + True + + + 1 + 4 + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + 0 + 0 + 1 + <b>Name:</b> + True + + + + + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <b>Path:</b> + True + + + + + 2 + 3 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + True + PANGO_WRAP_CHAR + True + + + 1 + 4 + 2 + 3 + + + + + + True + 0 + 1 + <b>Status:</b> + True + + + 5 + 6 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + + + 1 + 4 + 5 + 6 + + + + + + True + 0 + True + + + 1 + 2 + 3 + 4 + + + + + + + + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-properties + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Details + True + + + 1 + + + + + tab + 1 + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + + + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-copy + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Files + True + + + 1 + + + + + tab + 2 + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + + + 3 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-network + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Peers + True + + + 1 + + + + + tab + 3 + False + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + 5 + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + + + True + 0 + GTK_SHADOW_NONE + + + True + 12 + + + True + 5 + 4 + 3 + 5 + + + + + + + + + True + True + 6 + 1 + -1 -1 999999 1 10 10 + + + 1 + 2 + 2 + 3 + + + + + + + True + True + 6 + 1 + -1 -1 99999 1 10 10 + 1 + + + 1 + 2 + 1 + 2 + + + + + + + True + True + 6 + 1 + -1 -1 999999 1 10 10 + 1 + + + 1 + 2 + + + + + + + True + 0 + Max Connections: + + + 2 + 3 + GTK_FILL + + + + + + True + 0 + Max Upload Speed: + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + Max Download Speed: + + + GTK_FILL + + + + + + True + KiB/s + + + 2 + 3 + + + + + + + True + KiB/s + + + 2 + 3 + 1 + 2 + + + + + + + True + 0 + Max Upload Slots: + + + 3 + 4 + GTK_FILL + + + + + + True + True + 6 + 1 + -1 -1 999999 1 10 10 + + + 1 + 2 + 3 + 4 + + + + + + + + + + + True + <b>Bandwidth</b> + True + + + label_item + + + + + False + False + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 5 + 12 + + + True + + + True + True + Auto Managed + 0 + True + + + False + False + + + + + True + + + True + 5 + + + True + True + Stop seed at ratio: + 0 + True + + + False + False + + + + + True + True + 1 + 2 0 999 0.10000000000000001 10 10 + 2 + + + False + False + 1 + + + + + False + False + + + + + True + 10 + + + True + True + Remove at ratio + 0 + True + + + + + False + False + 1 + + + + + 1 + + + + + + + + + True + <b>Queue</b> + True + + + label_item + + + + + False + False + 1 + + + + + True + + + True + 0 + GTK_SHADOW_NONE + + + True + 5 + 12 + + + True + + + True + False + True + Private + 0 + True + + + False + False + + + + + True + True + Prioritize First/Last + 0 + True + + + False + False + 1 + + + + + True + True + True + 0 + + + + True + 5 + + + True + gtk-edit + + + False + False + + + + + True + _Edit Trackers + True + + + False + False + 1 + + + + + + + False + False + 2 + + + + + + + + + True + <b>General</b> + True + + + label_item + + + + + False + False + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 12 + + + True + True + True + gtk-apply + True + 0 + + + + + + + + + label_item + + + + + False + False + 1 + + + + + False + False + 2 + + + + + + + + + 4 + + + + + True + 2 + + + True + gtk-preferences + + + + + True + _Options + True + + + 1 + + + + + tab + 4 + False + + + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Remove Torrent? + False + GTK_WIN_POS_CENTER_ON_PARENT + GDK_WINDOW_TYPE_HINT_DIALOG + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-dialog-warning + 6 + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <big><b>Are you sure you want to remove the selected torrent?</b></big> + True + True + + + False + False + 1 + + + + + False + False + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 15 + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-dialog-warning + + + False + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <i>The associated .torrent will be deleted!</i> + True + + + 1 + + + + + + + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 15 + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-dialog-warning + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <i>The downloaded data will be deleted!</i> + True + + + 1 + + + + + + + 3 + + + + + False + False + 5 + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_CENTER + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + 0 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Remove Selected Torrent + 0 + + + 1 + + + + + False + GTK_PACK_END + + + + + + + 5 + New Release + GTK_WIN_POS_CENTER_ON_PARENT + deluge + GDK_WINDOW_TYPE_HINT_DIALOG + False + + + True + 2 + + + True + 10 + 5 + + + True + 5 + + + True + deluge + + + False + False + + + + + True + <b><big>New Release Available!</big></b> + True + + + False + False + 1 + + + + + False + False + + + + + True + + + False + 1 + + + + + True + 5 + + + True + 2 + 2 + 10 + 2 + + + True + + + 1 + 2 + 1 + 2 + + + + + + True + 0 + <i>Available Version:</i> + True + + + 1 + 2 + GTK_FILL + + + + + True + + + 1 + 2 + + + + + + True + 0 + <i>Current Version:</i> + True + + + GTK_FILL + + + + + + + 2 + + + + + True + 5 + + + True + True + Do not show this dialog in the future + 0 + True + + + + + 3 + + + + + False + False + 1 + + + + + True + GTK_BUTTONBOX_END + + + True + True + True + gtk-close + True + 0 + + + False + False + + + + + True + True + True + _Goto Website + True + 0 + + + + False + False + 1 + + + + + False + False + GTK_PACK_END + + + + + + diff --git a/deluge/ui/gtkui/glade/preferences_dialog.glade b/deluge/ui/gtkui/glade/preferences_dialog.glade new file mode 100644 index 000000000..01c7cf4be --- /dev/null +++ b/deluge/ui/gtkui/glade/preferences_dialog.glade @@ -0,0 +1,2761 @@ + + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Preferences + GTK_WIN_POS_CENTER_ON_PARENT + 510 + 530 + True + GDK_WINDOW_TYPE_HINT_DIALOG + False + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + False + True + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0.05000000074505806 + 10 + <b><i><big>Downloads</big></i></b> + True + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 2 + 2 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Show the Add Torrents dialog when adding files from an external source + Always show + 0 + True + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Bring the Add Torrents dialog to focus + Bring the dialog to focus + 0 + True + + + + + 1 + + + + + + + + + True + <b>Add Torrents Dialog</b> + True + + + label_item + + + + + False + False + 5 + 2 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + + + True + 2 + 2 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Default download location: + + + False + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER + Select A Folder + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + 2 + + + + + + + + + True + 2 + 2 + 12 + + + True + + + True + True + Move completed to: + 0 + True + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER + Select A Folder + + + 1 + + + + + True + + + 2 + + + + + + + 1 + + + + + + + True + <b>Download Location</b> + True + + + label_item + + + + + False + False + 5 + 3 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + True + Save copy of .torrent file: + 0 + True + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER + Select A Folder + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + 2 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Torrent File Copy</b> + True + + + label_item + + + + + False + False + 5 + 4 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Enable Folder: + 0 + True + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + 2 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Auto Add Folder</b> + True + + + label_item + + + + + False + False + 5 + 5 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 2 + 2 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Full allocation preallocates all of the space that is needed for the torrent and prevents disk fragmentation + Use Full Allocation + 0 + True + True + + + False + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Compact allocation only allocates space as needed + Use Compact Allocation + 0 + True + radio_full_allocation + + + False + False + 1 + + + + + + + + + True + <b>Allocation</b> + True + + + label_item + + + + + False + False + 5 + 6 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 2 + 2 + 12 + + + True + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Prioritize first and last pieces of files in torrent + Prioritize first and last pieces of torrent + 0 + True + + + False + + + + + + + + + True + <b>Options</b> + True + + + label_item + + + + + False + False + 5 + 7 + + + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + page 6 + + + tab + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0.05000000074505806 + 10 + <b><i><big>Network</big></i></b> + True + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 2 + 2 + 12 + + + True + + + True + + + True + From: + + + False + + + + + True + False + True + 5 + 1 + 0 0 65535 1 10 10 + 1 + True + True + + + False + 5 + 1 + + + + + True + 5 + To: + + + False + False + 2 + + + + + True + False + True + 5 + 1 + 0 0 65535 1 10 10 + 1 + True + True + + + False + 5 + 3 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Test Active Port + 0 + + + + False + False + 4 + + + + + 5 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 20 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Deluge will automatically choose a different port to use every time. + Use Random Ports + 0 + True + + + + False + 5 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + 1 + Active Port: + GTK_JUSTIFY_RIGHT + + + False + 5 + + + + + True + 0 + 0000 + 5 + + + False + 5 + 1 + + + + + False + 5 + 1 + + + + + 5 + 1 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Ports</b> + True + + + label_item + + + + + False + 5 + 2 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 2 + 2 + 12 + + + True + + + True + True + Distributed hash table may improve the amount of active connections. + Enable Mainline DHT + True + 0 + True + + + + + + + + + True + <b>DHT</b> + True + + + label_item + + + + + False + 5 + 3 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 2 + 2 + 12 + + + True + 10 + + + True + True + Universal Plug and Play + UPnP + True + 0 + True + True + + + False + 2 + + + + + True + True + NAT Port Mapping Protocol + NAT-PMP + True + 0 + True + True + + + False + 2 + 1 + + + + + True + True + Peer Exchange + Peer Exchange + True + 0 + True + True + + + False + 2 + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Local Service Discovery finds local peers on your network. + LSD + 0 + True + + + False + False + 3 + + + + + + + + + True + <b>Network Extras</b> + True + + + label_item + + + + + False + 5 + 4 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 2 + 2 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + 1 + Inbound: + + + + + True + 0 + Level: + + + 1 + + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + Forced +Enabled +Disabled + + + + + True + Handshake +Full Stream +Either + + + 1 + + + + + False + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + 1 + Outbound: + + + False + False + + + + + True + Forced +Enabled +Disabled + + + False + 1 + + + + + + + True + True + Encrypt entire stream + True + 0 + True + + + False + 3 + 1 + + + + + 2 + + + + + + + + + True + <b>Encryption</b> + True + + + label_item + + + + + False + False + 5 + 5 + + + + + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + page 7 + + + tab + 1 + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0.05000000074505806 + 10 + <b><i><big>Bandwidth</big></i></b> + True + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 2 + 2 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 4 + 2 + 15 + + + True + True + The maximum upload slots for all torrents. Set -1 for unlimited. + 1 + -1 -1 9000 1 10 10 + 1 + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + The maximum upload speed for all torrents. Set -1 for unlimited. + 1 + -1 -1 9000 1 10 10 + 1 + 1 + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + The maximum download speed for all torrents. Set -1 for unlimited. + 1 + -1 -1 9000 1 10 10 + 1 + 1 + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + The maximum download speed for all torrents. Set -1 for unlimited. + 0 + Maximum Download Speed (KiB/s): + + + 2 + 3 + GTK_FILL + + + + + True + True + The maximum number of connections allowed. Set -1 for unlimited. + 4 + 1 + -1 -1 9000 1 10 10 + 1 + True + True + GTK_UPDATE_IF_VALID + + + 1 + 2 + GTK_FILL + + + + + True + The maximum upload speed for all torrents. Set -1 for unlimited. + 0 + Maximum Upload Slots: + + + 1 + 2 + GTK_FILL + + + + + True + The maximum number of connections allowed. Set -1 for unlimited. + 0 + Maximum Connections: + + + GTK_FILL + + + + + True + The maximum upload speed for all torrents. Set -1 for unlimited. + 0 + Maximum Upload Speed (KiB/s): + + + 3 + 4 + GTK_FILL + + + + + + + + + True + <b>Global Bandwidth Usage</b> + True + + + label_item + + + + + False + False + 5 + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + 2 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 4 + 2 + 15 + + + True + True + The maximum upload slots per torrent. Set -1 for unlimited. + 1 + -1 -1 9000 1 10 10 + 1 + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + The maximum number of connections per torrent. Set -1 for unlimited. + 1 + -1 -1 9000 1 10 10 + True + True + + + 1 + 2 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Maximum Connections: + + + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Maximum Upload Slots: + + + 1 + 2 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Maximum Download Speed (KiB/s): + + + 2 + 3 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Maximum Upload Speed (KiB/s): + + + 3 + 4 + GTK_FILL + + + + + True + True + The maximum number of connections per torrent. Set -1 for unlimited. + 1 + -1 -1 9000 1 10 10 + 1 + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + The maximum number of connections per torrent. Set -1 for unlimited. + 1 + -1 -1 9000 1 10 10 + 1 + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Per Torrent Bandwidth Usage</b> + True + + + label_item + + + + + False + 5 + 3 + + + + + + + + + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + page 8 + + + tab + 2 + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0.05000000074505806 + 10 + <i><b><big>Interface</big></b></i> + True + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 2 + 2 + 12 + + + True + + + True + Enable system tray icon + True + 0 + True + + + + + + True + 10 + + + True + False + Minimize to tray on close + True + 0 + True + + + + + 1 + + + + + True + 10 + + + True + False + Start in tray + True + 0 + True + + + + + 2 + + + + + True + 3 + 10 + + + True + False + True + Password protect system tray + True + 0 + True + + + + + + False + 3 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 20 + + + True + 5 + + + True + False + 0 + Password: + + + False + + + + + True + False + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + 16 + ******** + + + False + 1 + + + + + + + 4 + + + + + + + + + True + <b>System Tray</b> + True + + + label_item + + + + + False + 5 + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + 2 + 12 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Enable + 0 + True + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Classic Mode</b> + True + + + label_item + + + + + False + False + 3 + + + + + + + + + 3 + + + + + + tab + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0.05000000074505806 + 10 + <i><b><big>Other</big></b></i> + True + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Deluge will check our servers and will tell you if a newer version has been released + Be alerted about new releases + 0 + True + + + + + False + False + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Updates</b> + True + + + label_item + + + + + False + False + 5 + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Help us improve Deluge by sending us your Python version, PyGTK version, OS and processor types. Absolutely no other information is sent. + True + + + False + False + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Yes, please send anonymous statistics + 0 + True + + + + + False + 1 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>System Information</b> + True + + + label_item + + + + + False + False + 5 + 3 + + + + + + + + + 5 + + + + + + tab + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0.05000000074505806 + 10 + <i><b><big>Daemon</big></b></i> + True + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Daemon port: + + + False + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + 0 0 65535 1 10 10 + + + False + False + 1 + + + + + False + False + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Port</b> + True + + + label_item + + + + + False + False + 5 + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 10 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Allow Remote Connections + 0 + True + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Connections</b> + True + + + label_item + + + + + False + False + 5 + 3 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 10 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Periodically check the website for new releases + 0 + True + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Other</b> + True + + + label_item + + + + + False + False + 5 + 4 + + + + + + + + + 5 + + + + + + tab + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0.05000000074505806 + 10 + <i><b><big>Queue</big></b></i> + True + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Queue new torrents to top + 0 + True + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>General</b> + True + + + label_item + + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 12 + + + True + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 3 + 2 + 10 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + 0 -1 9999 1 10 10 + True + True + + + 1 + 2 + + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + 0 -1 9999 1 10 10 + True + True + + + 1 + 2 + 2 + 3 + + + + + + True + 0 + Total active seeding: + + + 2 + 3 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Total active: + + + GTK_FILL + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + 0 -1 9999 1 10 10 + True + True + + + 1 + 2 + 1 + 2 + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Total active downloading: + + + 1 + 2 + GTK_FILL + + + + + + + True + True + Do not count slow torrents + 0 + True + + + 1 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Active Torrents</b> + True + + + label_item + + + + + False + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + 3 + 2 + 10 + + + True + 0 + Share Ratio Limit: + + + GTK_FILL + + + + + True + 0 + Seed Time Ratio: + + + 1 + 2 + GTK_FILL + + + + + True + 0 + Seed Time (m): + + + 2 + 3 + GTK_FILL + + + + + True + True + 6 + 1 + 1.5 -1 100 0.10000000000000001 10 10 + 2 + + + 1 + 2 + + + + + + True + True + 6 + 1 + 6 -1 100 0.10000000000000001 10 10 + 2 + + + 1 + 2 + 1 + 2 + + + + + + True + True + 6 + 1 + 6 -1 100 1 10 10 + + + 1 + 2 + 2 + 3 + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Stop seeding when share ratio reaches: + 0 + True + + + + False + False + + + + + True + False + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + 2 0.5 100 0.10000000000000001 1 1 + 2 + True + + + False + False + 1 + + + + + False + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + False + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Remove torrent when share ratio reached + 0 + True + + + + + 2 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Seeding</b> + True + + + label_item + + + + + False + False + 2 + + + + + 5 + 2 + + + + + + + + + 6 + + + + + + tab + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0.05000000074505806 + 10 + <i><b><big>Plugins</big></b></i> + True + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + False + True + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + GTK_WRAP_WORD + False + False + + + False + True + + + + + 2 + + + + + + + + + 7 + + + + + + tab + + + + + True + True + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + 0 + + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-apply + True + 0 + + + + 1 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-ok + True + 0 + + + + 2 + + + + + False + GTK_PACK_END + + + + + + diff --git a/deluge/ui/gtkui/glade/queuedtorrents.glade b/deluge/ui/gtkui/glade/queuedtorrents.glade new file mode 100644 index 000000000..ed59466bb --- /dev/null +++ b/deluge/ui/gtkui/glade/queuedtorrents.glade @@ -0,0 +1,189 @@ + + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Queued Torrents + GTK_WIN_POS_CENTER_ON_PARENT + 450 + 300 + True + GDK_WINDOW_TYPE_HINT_DIALOG + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-add + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0.05000000074505806 + 10 + <big><b>Add Queued Torrents</b></big> + True + + + False + False + 1 + + + + + False + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_START + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-remove + True + 0 + + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-clear + True + 0 + + + + 1 + + + + + False + False + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Automatically add torrents on connect + 0 + True + + + + False + False + 3 + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-close + True + 0 + + + + + + True + False + True + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-add + True + 0 + + + + 1 + + + + + False + GTK_PACK_END + + + + + + diff --git a/deluge/ui/gtkui/glade/remove_torrent_dialog.glade b/deluge/ui/gtkui/glade/remove_torrent_dialog.glade new file mode 100644 index 000000000..addf5689d --- /dev/null +++ b/deluge/ui/gtkui/glade/remove_torrent_dialog.glade @@ -0,0 +1,196 @@ + + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Remove Torrent? + False + GTK_WIN_POS_CENTER_ON_PARENT + GDK_WINDOW_TYPE_HINT_DIALOG + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-dialog-warning + 6 + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <big><b>Are you sure you want to remove the selected torrent?</b></big> + True + True + + + False + False + 1 + + + + + False + False + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 15 + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-dialog-warning + + + False + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <i>The associated .torrent will be deleted!</i> + True + + + 1 + + + + + + + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 15 + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-dialog-warning + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <i>The downloaded data will be deleted!</i> + True + + + 1 + + + + + + + 3 + + + + + False + False + 5 + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_CENTER + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + 0 + + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Remove Selected Torrent + 0 + + + + 1 + + + + + False + GTK_PACK_END + + + + + + diff --git a/deluge/ui/gtkui/glade/torrent_menu.glade b/deluge/ui/gtkui/glade/torrent_menu.glade new file mode 100644 index 000000000..60fa3fb99 --- /dev/null +++ b/deluge/ui/gtkui/glade/torrent_menu.glade @@ -0,0 +1,361 @@ + + + + + + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Open Folder + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-open + 1 + + + + + + + True + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Pause + True + + + + gtk-media-pause + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Resume selected torrents. + Resu_me + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-media-play + 1 + + + + + + + True + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Opt_ions + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-preferences + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Queue + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-sort-descending + 1 + + + + + + + True + + + + + True + _Update Tracker + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-refresh + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Edit Trackers + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-edit + 1 + + + + + + + True + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Remove Torrent + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-remove + 1 + + + + + + + True + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Force Re-check + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-redo + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Move _Storage + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-save-as + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + From Session + True + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + .. And Delete Torrent File + True + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + .. And Delete Downloaded Files + True + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + .. And Delete All Files + True + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Download Speed Limit + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-missing-image + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Upload Speed Limit + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-missing-image + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Connection Limit + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-network + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Upload _Slot Limit + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-sort-ascending + 1 + + + + + + + True + _Auto Managed + True + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-goto-top + True + True + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-go-up + True + True + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-go-down + True + True + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-goto-bottom + True + True + + + + + diff --git a/glade/tray_menu.glade b/deluge/ui/gtkui/glade/tray_menu.glade similarity index 78% rename from glade/tray_menu.glade rename to deluge/ui/gtkui/glade/tray_menu.glade index 37caec5da..eaca5a191 100644 --- a/glade/tray_menu.glade +++ b/deluge/ui/gtkui/glade/tray_menu.glade @@ -6,61 +6,26 @@ True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK _Show Deluge True - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Resume All - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-media-play - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Pause All - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-media-pause - 1 - - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK _Add Torrent True - + True @@ -72,21 +37,51 @@ - + True - Add _URL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Pause All True - + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-media-pause + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Resume All + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-media-play + 1 + + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK _Download Speed Limit @@ -102,7 +97,7 @@ - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK _Upload Speed Limit @@ -120,16 +115,37 @@ True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Quit & Shutdown Daemon + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-quit + 1 + + + + + + + True + + + + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK _Quit True - + True diff --git a/deluge/ui/gtkui/gtkui.py b/deluge/ui/gtkui/gtkui.py new file mode 100644 index 000000000..09213387f --- /dev/null +++ b/deluge/ui/gtkui/gtkui.py @@ -0,0 +1,235 @@ +# +# gtkui.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 +import pygtk +try: + pygtk.require('2.0') +except: + log.warning("It is suggested that you upgrade your PyGTK to 2.10 or greater.") +import gtk, gtk.glade +import gobject +import gettext +import locale +import pkg_resources +import signal + +import deluge.component as component +from deluge.ui.client import aclient as client +from mainwindow import MainWindow +from menubar import MenuBar +from toolbar import ToolBar +from torrentview import TorrentView +from torrentdetails import TorrentDetails +from sidebar import SideBar +from preferences import Preferences +from systemtray import SystemTray +from statusbar import StatusBar +from connectionmanager import ConnectionManager +from signals import Signals +from pluginmanager import PluginManager +from ipcinterface import IPCInterface + +from queuedtorrents import QueuedTorrents +from addtorrentdialog import AddTorrentDialog +from coreconfig import CoreConfig +import deluge.configmanager +import deluge.common + +DEFAULT_PREFS = { + "config_location": deluge.configmanager.get_config_dir(), + "classic_mode": True, + "interactive_add": True, + "focus_add_dialog": True, + "enable_system_tray": True, + "close_to_tray": True, + "start_in_tray": False, + "lock_tray": False, + "tray_password": "", + "check_new_releases": True, + "default_load_path": None, + "window_maximized": False, + "window_x_pos": 0, + "window_y_pos": 0, + "window_width": 640, + "window_height": 480, + "window_pane_position": -1, + "tray_download_speed_list" : [5.0, 10.0, 30.0, 80.0, 300.0], + "tray_upload_speed_list" : [5.0, 10.0, 30.0, 80.0, 300.0], + "connection_limit_list": [50, 100, 200, 300, 500], + "enabled_plugins": [], + "show_connection_manager_on_start": True, + "autoconnect": False, + "autoconnect_host_uri": None, + "autostart_localhost": False, + "autoadd_queued": False, + "autoadd_enable": False, + "autoadd_location": "", + "choose_directory_dialog_path": deluge.common.get_default_download_dir(), + "show_new_releases": True, + "signal_port": 40000 +} + +class GtkUI: + def __init__(self, args): + # Initialize gdk threading + gtk.gdk.threads_init() + gobject.threads_init() + + # Initialize gettext + if deluge.common.windows_check(): + locale.setlocale(locale.LC_ALL, '') + else: + locale.setlocale(locale.LC_MESSAGES, '') + locale.bindtextdomain("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) + locale.textdomain("deluge") + + gettext.bindtextdomain("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) + gettext.textdomain("deluge") + gettext.install("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) + + # Setup signals + try: + import gnome.ui + self.gnome_client = gnome.ui.Client() + self.gnome_client.connect("die", self.shutdown) + except: + pass + signal.signal(signal.SIGINT, self.shutdown) + signal.signal(signal.SIGTERM, self.shutdown) + + if deluge.common.windows_check(): + from win32api import SetConsoleCtrlHandler + from win32con import CTRL_CLOSE_EVENT + result = 0 + def win_handler(ctrl_type): + if ctrl_type == CTRL_CLOSE_EVENT: + self.shutdown() + return 1 + SetConsoleCtrlHandler(win_handler) + + # Make sure gtkui.conf has at least the defaults set + self.config = deluge.configmanager.ConfigManager("gtkui.conf", DEFAULT_PREFS) + + # We need to check for the existence of 'deluged' in the system path + # before allowing to continue in classic mode. + if self.config["classic_mode"]: + try: + if deluge.common.windows_check(): + import win32api + win32api.WinExec("deluged --version") + else: + import subprocess + retcode = subprocess.call("deluged" + " --version", shell=True) + log.debug("retcode: %s", retcode) + if retcode == 127: + log.error("Unable to find deluged!") + self.config["classic_mode"] = False + except Exception, e: + log.error("Unable to find deluged: %s", e) + self.config["classic_mode"] = False + + # We need to check on exit if it was started in classic mode to ensure we + # shutdown the daemon. + self.started_in_classic = self.config["classic_mode"] + + # Start the Dbus Interface before anything else.. Just in case we are + # already running. + self.queuedtorrents = QueuedTorrents() + + self.ipcinterface = IPCInterface(args) + + # We make sure that the UI components start once we get a core URI + client.connect_on_new_core(self._on_new_core) + client.connect_on_no_core(self._on_no_core) + + # Initialize various components of the gtkui + self.mainwindow = MainWindow() + self.menubar = MenuBar() + self.toolbar = ToolBar() + self.torrentview = TorrentView() + self.torrentdetails = TorrentDetails() + self.sidebar = SideBar() + self.preferences = Preferences() + self.systemtray = SystemTray() + self.statusbar = StatusBar() + self.addtorrentdialog = AddTorrentDialog() + + # Start the signal receiver + self.signal_receiver = Signals() + self.coreconfig = CoreConfig() + + # Initalize the plugins + self.plugins = PluginManager() + + # Show the connection manager + self.connectionmanager = ConnectionManager() + if self.config["show_connection_manager_on_start"] and not self.config["classic_mode"]: + self.connectionmanager.show() + + # Start the gtk main loop + try: + gtk.gdk.threads_enter() + gtk.main() + gtk.gdk.threads_leave() + except KeyboardInterrupt: + self.shutdown() + else: + self.shutdown() + + def shutdown(self, data=None): + log.debug("gtkui shutting down..") + + # Make sure the config is saved. + self.config.save() + + # Shutdown all components + component.shutdown() + if self.started_in_classic: + try: + client.shutdown() + except: + pass + + + def _on_new_core(self, data): + component.start() + + def _on_no_core(self, data): + component.stop() diff --git a/deluge/ui/gtkui/ipcinterface.py b/deluge/ui/gtkui/ipcinterface.py new file mode 100644 index 000000000..d874502d5 --- /dev/null +++ b/deluge/ui/gtkui/ipcinterface.py @@ -0,0 +1,104 @@ +# +# ipcinterface.py +# +# Copyright (C) 2008 Andrew Resch ('andar') +# +# 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 2 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.path + +import deluge.component as component +from deluge.ui.client import aclient as client +import deluge.common +from deluge.configmanager import ConfigManager +from deluge.log import LOG as log + +class IPCInterface(component.Component): + def __init__(self, args): + component.Component.__init__(self, "IPCInterface") + + if deluge.common.windows_check(): + # If we're on windows we need to check the global mutex to see if deluge is + # already running. + import win32event + import win32api + import winerror + self.mutex = win32event.CreateMutex(None, False, "deluge") + if win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS: + # We already have a running session, send a XMLRPC to the existing session + uri = "http://localhost:" + str(self.config["signal_port"]) + rpc = xmlrpclib.ServerProxy(uri, allow_none=True) + rpc.args_from_external(args) + sys.exit(0) + else: + try: + import dbusinterface + self.dbusinterface = dbusinterface.DbusInterface(args) + except Exception, e: + log.warning("Unable to start DBUS component: %s", e) + + def shutdown(self): + if deluge.common.windows_check(): + import win32api + win32api.CloseHandle(self.mutex) + +def process_args(args): + """Process arguments sent to already running Deluge""" + # Pythonize the values from Dbus + dbus_args = args + args = [] + for arg in dbus_args: + args.append(str(arg)) + log.debug("Processing args from other process: %s", args) + if not client.connected(): + # We're not connected so add these to the queue + log.debug("Not connected to host.. Adding to queue.") + component.get("QueuedTorrents").add_to_queue(args) + return + config = ConfigManager("gtkui.conf") + for arg in args: + if deluge.common.is_url(arg): + log.debug("Attempting to add %s from external source..", + arg) + if config["interactive_add"]: + component.get("AddTorrentDialog").add_from_url(arg) + component.get("AddTorrentDialog").show(config["focus_add_dialog"]) + else: + client.add_torrent_url(arg) + else: + # Just a file + log.debug("Attempting to add %s from external source..", + os.path.abspath(arg)) + if config["interactive_add"]: + component.get("AddTorrentDialog").add_from_files([os.path.abspath(arg)]) + component.get("AddTorrentDialog").show(config["focus_add_dialog"]) + else: + client.add_torrent_file([os.path.abspath(arg)]) + diff --git a/deluge/ui/gtkui/listview.py b/deluge/ui/gtkui/listview.py new file mode 100644 index 000000000..708853df0 --- /dev/null +++ b/deluge/ui/gtkui/listview.py @@ -0,0 +1,492 @@ +# +# listview.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 cPickle +import os.path + +import pygtk +pygtk.require('2.0') +import gtk +import gettext + +from deluge.configmanager import ConfigManager +import deluge.common +from deluge.log import LOG as log + +# Cell data functions to pass to add_func_column() +def cell_data_speed(column, cell, model, row, data): + """Display value as a speed, eg. 2 KiB/s""" + speed = model.get_value(row, data) + speed_str = "" + if speed > 0: + speed_str = deluge.common.fspeed(speed) + + cell.set_property('text', speed_str) + +def cell_data_size(column, cell, model, row, data): + """Display value in terms of size, eg. 2 MB""" + size = model.get_value(row, data) + size_str = deluge.common.fsize(size) + cell.set_property('text', size_str) + +def cell_data_peer(column, cell, model, row, data): + """Display values as 'value1 (value2)'""" + (first, second) = model.get(row, *data) + # Only display a (total) if second is greater than -1 + if second > -1: + cell.set_property('text', '%d (%d)' % (first, second)) + else: + cell.set_property('text', '%d' % first) + +def cell_data_time(column, cell, model, row, data): + """Display value as time, eg 1m10s""" + time = model.get_value(row, data) + if time <= 0: + time_str = "" + else: + time_str = deluge.common.ftime(time) + cell.set_property('text', time_str) + +def cell_data_ratio(column, cell, model, row, data): + """Display value as a ratio with a precision of 3.""" + ratio = model.get_value(row, data) + if ratio == -1: + ratio_str = _("Unknown") + else: + ratio_str = "%.3f" % ratio + + cell.set_property('text', ratio_str) + +class ListViewColumnState: + """Used for saving/loading column state""" + def __init__(self, name, position, width, visible, sort, sort_order): + self.name = name + self.position = position + self.width = width + self.visible = visible + self.sort = sort + self.sort_order = sort_order + +class ListView: + """ListView is used to make custom GtkTreeViews. It supports the adding + and removing of columns, creating a menu for a column toggle list and + support for 'status_field's which are used while updating the columns data. + """ + + class ListViewColumn: + """Holds information regarding a column in the ListView""" + def __init__(self, name, column_indices): + # Name is how a column is identified and is also the header + self.name = name + # Column_indices holds the indexes to the liststore_columns that + # this column utilizes. It is stored as a list. + self.column_indices = column_indices + # Column is a reference to the GtkTreeViewColumn object + self.column = None + # This is the name of the status field that the column will query + # the core for if an update is called. + self.status_field = None + # If column is 'hidden' then it will not be visible and will not + # show up in any menu listing; it cannot be shown ever. + self.hidden = False + + def __init__(self, treeview_widget=None): + log.debug("ListView initialized..") + + if treeview_widget is not None: + # User supplied a treeview widget + self.treeview = treeview_widget + else: + self.treeview = gtk.TreeView() + + self.liststore = None + + self.treeview.set_model(self.liststore) + self.treeview.set_rules_hint(True) + self.treeview.set_reorderable(True) + self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) + + # Dictionary of 'header' or 'name' to ListViewColumn object + self.columns = {} + # Column_index keeps track of the order of the visible columns. + self.column_index = [] + # The column types for the list store.. this may have more entries than + # visible columns due to some columns utilizing more than 1 liststore + # column and some columns being hidden. + self.liststore_columns = [] + # The GtkMenu that is created after every addition, removal or reorder + self.menu = None + # A list of menus that self.menu will be a submenu of everytime it is + # created. + self.checklist_menus = [] + + def save_state(self, filename): + """Saves the listview state (column positions and visibility) to + filename.""" + # A list of ListViewColumnStates + state = [] + + # Get the list of TreeViewColumns from the TreeView + treeview_columns = self.treeview.get_columns() + counter = 0 + for column in treeview_columns: + # Append a new column state to the state list + state.append(ListViewColumnState(column.get_title(), counter, + column.get_width(), column.get_visible(), + column.get_sort_indicator(), int(column.get_sort_order()))) + # Increase the counter because this is how we determine position + counter += 1 + + # Get the config location for saving the state file + config_location = ConfigManager("gtkui.conf")["config_location"] + + try: + log.debug("Saving ListView state file: %s", filename) + state_file = open(os.path.join(config_location, filename), "wb") + cPickle.dump(state, state_file) + state_file.close() + except IOError, e: + log.warning("Unable to save state file: %s", e) + + def load_state(self, filename): + """Load the listview state from filename.""" + # Get the config location for loading the state file + config_location = ConfigManager("gtkui.conf")["config_location"] + state = None + + try: + log.debug("Loading ListView state file: %s", filename) + state_file = open(os.path.join(config_location, filename), "rb") + state = cPickle.load(state_file) + state_file.close() + except (EOFError, IOError), e: + log.warning("Unable to load state file: %s", e) + + # Keep the state in self.state so we can access it as we add new columns + self.state = state + + def set_treeview(self, treeview_widget): + """Set the treeview widget that this listview uses.""" + self.treeview = treeview_widget + self.treeview.set_model(self.liststore) + return + + def get_column_index(self, name): + """Get the liststore column indices belonging to this column. + Will return a list if greater than 1 column. + """ + # Only return as list if needed + if len(self.columns[name].column_indices) > 1: + return self.columns[name].column_indices + else: + return self.columns[name].column_indices[0] + + def get_state_field_column(self, field): + """Returns the column number for the state field""" + for column in self.columns.keys(): + if self.columns[column].status_field == None: + continue + + for f in self.columns[column].status_field: + if field == f: + return self.columns[column].column_indices[ + self.columns[column].status_field.index(f)] + + def on_menuitem_toggled(self, widget): + """Callback for the generated column menuitems.""" + # Get the column name from the widget + name = widget.get_child().get_text() + + # Set the column's visibility based on the widgets active state + self.columns[name].column.set_visible(widget.get_active()) + return + + def register_checklist_menu(self, menu): + """Register a checklist menu with the listview. It will automatically + attach any new checklist menu it makes to this menu. + """ + self.checklist_menus.append(menu) + + def create_checklist_menu(self): + """Creates a menu used for toggling the display of columns.""" + menu = gtk.Menu() + # Iterate through the column_index list to preserve order + for name in self.column_index: + column = self.columns[name] + # If the column is hidden, then we do not want to show it in the + # menu. + if column.hidden is True: + continue + menuitem = gtk.CheckMenuItem(column.name) + # If the column is currently visible, make sure it's set active + # (or checked) in the menu. + if column.column.get_visible() is True: + menuitem.set_active(True) + # Connect to the 'toggled' event + menuitem.connect("toggled", self.on_menuitem_toggled) + # Add the new checkmenuitem to the menu + menu.append(menuitem) + + # Attach this new menu to all the checklist_menus + for _menu in self.checklist_menus: + _menu.set_submenu(menu) + _menu.show_all() + + return menu + + def create_new_liststore(self): + """Creates a new GtkListStore based on the liststore_columns list""" + # Create a new liststore with added column and move the data from the + # old one to the new one. + new_list = gtk.ListStore(*tuple(self.liststore_columns)) + + # This function is used in the liststore.foreach method with user_data + # being the new liststore and the columns list + def copy_row(model, path, row, user_data): + new_list, columns = user_data + new_row = new_list.append() + for column in range(len(columns)): + # Get the current value of the column for this row + value = model.get_value(row, column) + # Set the value of this row and column in the new liststore + new_list.set_value(new_row, column, value) + + # Do the actual row copy + if self.liststore is not None: + self.liststore.foreach(copy_row, (new_list, self.columns)) + + self.liststore = new_list + self.treeview.set_model(self.liststore) + + return + + def remove_column(self, header): + """Removes the column with the name 'header' from the listview""" + # Start by removing this column from the treeview + self.treeview.remove_column(self.columns[header].column) + # Get the column indices + column_indices = self.columns[header].column_indices + # Delete the column + del self.columns[header] + self.column_index.remove(header) + # Shift the column_indices values of those columns effected by the + # removal. Any column_indices > the one removed. + for column in self.columns.values(): + if column.column_indices[0] > column_indices[0]: + # We need to shift this column_indices + for index in column.column_indices: + index = index - len(column_indices) + + # Remove from the liststore columns list + for index in column_indices: + del self.liststore_columns[index] + + # Create a new liststore + self.create_new_liststore() + + # Re-create the menu + self.create_checklist_menu() + + return + + def add_column(self, header, render, col_types, hidden, position, + status_field, sortid, text=0, value=0, pixbuf=0, function=None, + column_type=None): + """Adds a column to the ListView""" + # Add the column types to liststore_columns + column_indices = [] + if type(col_types) is list: + for col_type in col_types: + self.liststore_columns.append(col_type) + column_indices.append(len(self.liststore_columns) - 1) + else: + self.liststore_columns.append(col_types) + column_indices.append(len(self.liststore_columns) - 1) + + # Add to the index list so we know the order of the visible columns. + if position is not None: + self.column_index.insert(position, header) + else: + self.column_index.append(header) + + # Create a new column object and add it to the list + self.columns[header] = self.ListViewColumn(header, column_indices) + + self.columns[header].status_field = status_field + + # Create a new list with the added column + self.create_new_liststore() + + column = gtk.TreeViewColumn(header) + if column_type == "text": + column.pack_start(render) + column.add_attribute(render, "text", + self.columns[header].column_indices[text]) + elif column_type == "bool": + column.pack_start(render) + column.add_attribute(render, "active", + self.columns[header].column_indices[0]) + elif column_type == "func": + column.pack_start(render, True) + if len(self.columns[header].column_indices) > 1: + column.set_cell_data_func(render, function, + tuple(self.columns[header].column_indices)) + else: + column.set_cell_data_func(render, function, + self.columns[header].column_indices[0]) + elif column_type == "progress": + column.pack_start(render) + if function is None: + column.add_attribute(render, "text", + self.columns[header].column_indices[text]) + column.add_attribute(render, "value", + self.columns[header].column_indices[value]) + else: + column.set_cell_data_func(render, function, + tuple(self.columns[header].column_indices)) + elif column_type == "texticon": + column.pack_start(render[pixbuf], False) + if function is not None: + column.set_cell_data_func(render[pixbuf], function, + self.columns[header].column_indices[pixbuf]) + column.pack_start(render[text], True) + column.add_attribute(render[text], "text", + self.columns[header].column_indices[text]) + elif column_type == None: + return + + column.set_sort_column_id(self.columns[header].column_indices[sortid]) + column.set_clickable(True) + column.set_resizable(True) + column.set_expand(False) + column.set_min_width(10) + column.set_reorderable(True) + column.set_visible(not hidden) + + # Check for loaded state and apply + if self.state != None: + for column_state in self.state: + if header == column_state.name: + # We found a loaded state + if column_state.width > 0: + column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + column.set_fixed_width(column_state.width) + column.set_sort_indicator(column_state.sort) + column.set_sort_order(column_state.sort_order) + column.set_visible(column_state.visible) + position = column_state.position + + if position is not None: + self.treeview.insert_column(column, position) + else: + self.treeview.append_column(column) + + # Set hidden in the column + self.columns[header].hidden = hidden + self.columns[header].column = column + # Re-create the menu item because of the new column + self.create_checklist_menu() + + return True + + def add_text_column(self, header, col_type=str, hidden=False, + position=None, + status_field=None, + sortid=0, + column_type="text"): + """Add a text column to the listview. Only the header name is required. + """ + render = gtk.CellRendererText() + self.add_column(header, render, col_type, hidden, position, + status_field, sortid, column_type=column_type) + + return True + + def add_bool_column(self, header, col_type=bool, hidden=False, + position=None, + status_field=None, + sortid=0, + column_type="bool"): + + """Add a bool column to the listview""" + render = gtk.CellRendererToggle() + self.add_column(header, render, col_type, hidden, position, + status_field, sortid, column_type=column_type) + + def add_func_column(self, header, function, col_types, sortid=0, + hidden=False, position=None, status_field=None, + column_type="func"): + """Add a function column to the listview. Need a header name, the + function and the column types.""" + + render = gtk.CellRendererText() + self.add_column(header, render, col_types, hidden, position, + status_field, sortid, column_type=column_type, + function=function) + + return True + + def add_progress_column(self, header, col_types=[float, str], + sortid=0, + hidden=False, + position=None, + status_field=None, + function=None, + column_type="progress"): + """Add a progress column to the listview.""" + + render = gtk.CellRendererProgress() + self.add_column(header, render, col_types, hidden, position, + status_field, sortid, function=function, + column_type=column_type, + value=0, text=1) + + return True + + def add_texticon_column(self, header, col_types=[str, str], + sortid=1, + hidden=False, + position=None, + status_field=None, + column_type="texticon", + function=None): + """Adds a texticon column to the listview.""" + render1 = gtk.CellRendererPixbuf() + render2 = gtk.CellRendererText() + + self.add_column(header, (render1, render2), col_types, hidden, + position, status_field, sortid, + column_type=column_type, function=function, + pixbuf=0, text=1) + + return True diff --git a/deluge/ui/gtkui/mainwindow.py b/deluge/ui/gtkui/mainwindow.py new file mode 100644 index 000000000..c87226458 --- /dev/null +++ b/deluge/ui/gtkui/mainwindow.py @@ -0,0 +1,185 @@ +# +# mainwindow.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 pygtk +pygtk.require('2.0') +import gtk, gtk.glade +import gobject +import pkg_resources + +from deluge.ui.client import aclient as client +import deluge.component as component +from deluge.configmanager import ConfigManager + +import deluge.common + +from deluge.log import LOG as log + +class MainWindow(component.Component): + def __init__(self): + component.Component.__init__(self, "MainWindow") + self.config = ConfigManager("gtkui.conf") + # Get the glade file for the main window + self.main_glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/main_window.glade")) + + self.window = self.main_glade.get_widget("main_window") + self.window.set_icon(deluge.common.get_logo(32)) + self.vpaned = self.main_glade.get_widget("vpaned") + + # Load the window state + self.load_window_state() + + # Keep track of window's minimization state so that we don't update the + # UI when it is minimized. + self.is_minimized = False + + # Connect events + self.window.connect("window-state-event", self.on_window_state_event) + self.window.connect("configure-event", self.on_window_configure_event) + self.window.connect("delete-event", self.on_window_delete_event) + self.vpaned.connect("notify::position", self.on_vpaned_position_event) + + if not(self.config["start_in_tray"] and \ + self.config["enable_system_tray"]) and not \ + self.window.get_property("visible"): + log.debug("Showing window") + self.show() + + def show(self): + try: + component.resume("TorrentView") + component.resume("StatusBar") + component.resume("TorrentDetails") + except: + pass + + self.window.show() + + def hide(self): + component.pause("TorrentView") + component.pause("StatusBar") + component.pause("TorrentDetails") + # Store the x, y positions for when we restore the window + self.window_x_pos = self.window.get_position()[0] + self.window_y_pos = self.window.get_position()[1] + self.window.hide() + + def present(self): + # Restore the proper x,y coords for the window prior to showing it + try: + self.config["window_x_pos"] = self.window_x_pos + self.config["window_y_pos"] = self.window_y_pos + except: + pass + try: + component.resume("TorrentView") + component.resume("StatusBar") + component.resume("TorrentDetails") + except: + pass + + self.window.present() + self.load_window_state() + + def active(self): + """Returns True if the window is active, False if not.""" + return self.window.is_active() + + def visible(self): + """Returns True if window is visible, False if not.""" + return self.window.get_property("visible") + + def get_glade(self): + """Returns a reference to the main window glade object.""" + return self.main_glade + + def quit(self): + del self.config + gtk.main_quit() + + def load_window_state(self): + x = self.config["window_x_pos"] + y = self.config["window_y_pos"] + w = self.config["window_width"] + h = self.config["window_height"] + self.window.move(x, y) + self.window.resize(w, h) + if self.config["window_maximized"] == True: + self.window.maximize() + self.vpaned.set_position( + self.config["window_height"] - self.config["window_pane_position"]) + + def on_window_configure_event(self, widget, event): + if self.config["window_maximized"] == False and self.visible: + self.config.set("window_x_pos", self.window.get_position()[0]) + self.config.set("window_y_pos", self.window.get_position()[1]) + self.config.set("window_width", event.width) + self.config.set("window_height", event.height) + + def on_window_state_event(self, widget, event): + if event.changed_mask & gtk.gdk.WINDOW_STATE_MAXIMIZED: + if event.new_window_state & gtk.gdk.WINDOW_STATE_MAXIMIZED: + log.debug("pos: %s", self.window.get_position()) + self.config.set("window_maximized", True) + else: + self.config.set("window_maximized", False) + if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED: + if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED: + log.debug("MainWindow is minimized..") + component.pause("TorrentView") + component.pause("StatusBar") + self.is_minimized = True + else: + log.debug("MainWindow is not minimized..") + try: + component.resume("TorrentView") + component.resume("StatusBar") + except: + pass + self.is_minimized = False + return False + + def on_window_delete_event(self, widget, event): + if self.config["close_to_tray"] and self.config["enable_system_tray"]: + self.hide() + else: + self.quit() + + return True + + def on_vpaned_position_event(self, obj, param): + self.config.set("window_pane_position", + self.config["window_height"] - self.vpaned.get_position()) + diff --git a/deluge/ui/gtkui/menubar.py b/deluge/ui/gtkui/menubar.py new file mode 100644 index 000000000..fb65102a7 --- /dev/null +++ b/deluge/ui/gtkui/menubar.py @@ -0,0 +1,456 @@ +# +# menubar.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 pygtk +pygtk.require('2.0') +import gtk, gtk.glade +import pkg_resources + +import deluge.error +import deluge.component as component +from deluge.ui.client import aclient as client +import deluge.common as common +from deluge.configmanager import ConfigManager + +from deluge.log import LOG as log + +class MenuBar(component.Component): + def __init__(self): + log.debug("MenuBar init..") + component.Component.__init__(self, "MenuBar") + self.window = component.get("MainWindow") + self.config = ConfigManager("gtkui.conf") + + # Get the torrent menu from the glade file + self.torrentmenu_glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/torrent_menu.glade")) + + # Attach remove torrent menu + self.torrentmenu_glade.get_widget("menuitem_remove").set_submenu( + self.torrentmenu_glade.get_widget("remove_torrent_menu")) + + self.torrentmenu_glade.get_widget("menuitem_queue").set_submenu( + self.torrentmenu_glade.get_widget("queue_torrent_menu")) + + # Attach options torrent menu + self.torrentmenu_glade.get_widget("menuitem_options").set_submenu( + self.torrentmenu_glade.get_widget("options_torrent_menu")) + self.torrentmenu_glade.get_widget("download-limit-image").set_from_file( + common.get_pixmap("downloading16.png")) + self.torrentmenu_glade.get_widget("upload-limit-image").set_from_file( + common.get_pixmap("seeding16.png")) + + for menuitem in ("menuitem_down_speed", "menuitem_up_speed", + "menuitem_max_connections", "menuitem_upload_slots"): + submenu = gtk.Menu() + item = gtk.MenuItem(_("Set Unlimited")) + item.set_name(menuitem) + item.connect("activate", self.on_menuitem_set_unlimited) + submenu.append(item) + item = gtk.MenuItem(_("Other..")) + item.set_name(menuitem) + item.connect("activate", self.on_menuitem_set_other) + submenu.append(item) + submenu.show_all() + self.torrentmenu_glade.get_widget(menuitem).set_submenu(submenu) + + submenu = gtk.Menu() + item = gtk.MenuItem(_("On")) + item.connect("activate", self.on_menuitem_set_automanaged_on) + submenu.append(item) + item = gtk.MenuItem(_("Off")) + item.connect("activate", self.on_menuitem_set_automanaged_off) + submenu.append(item) + submenu.show_all() + self.torrentmenu_glade.get_widget("menuitem_auto_managed").set_submenu(submenu) + + self.torrentmenu = self.torrentmenu_glade.get_widget("torrent_menu") + self.menu_torrent = self.window.main_glade.get_widget("menu_torrent") + + # Attach the torrent_menu to the Torrent file menu + self.menu_torrent.set_submenu(self.torrentmenu) + + ### Connect Signals ### + self.window.main_glade.signal_autoconnect({ + ## File Menu + "on_menuitem_addtorrent_activate": \ + self.on_menuitem_addtorrent_activate, + "on_menuitem_quitdaemon_activate": \ + self.on_menuitem_quitdaemon_activate, + "on_menuitem_quit_activate": self.on_menuitem_quit_activate, + + ## Edit Menu + "on_menuitem_preferences_activate": \ + self.on_menuitem_preferences_activate, + "on_menuitem_connectionmanager_activate": \ + self.on_menuitem_connectionmanager_activate, + + ## View Menu + "on_menuitem_toolbar_toggled": self.on_menuitem_toolbar_toggled, + "on_menuitem_labels_toggled": self.on_menuitem_labels_toggled, + "on_menuitem_statusbar_toggled": self.on_menuitem_statusbar_toggled, + + ## Help Menu + "on_menuitem_homepage_activate": self.on_menuitem_homepage_activate, + "on_menuitem_faq_activate": self.on_menuitem_faq_activate, + "on_menuitem_community_activate": \ + self.on_menuitem_community_activate, + "on_menuitem_about_activate": self.on_menuitem_about_activate + }) + + self.torrentmenu_glade.signal_autoconnect({ + ## Torrent Menu + "on_menuitem_pause_activate": self.on_menuitem_pause_activate, + "on_menuitem_resume_activate": self.on_menuitem_resume_activate, + "on_menuitem_updatetracker_activate": \ + self.on_menuitem_updatetracker_activate, + "on_menuitem_edittrackers_activate": \ + self.on_menuitem_edittrackers_activate, + "on_menuitem_remove_session_activate": \ + self.on_menuitem_remove_session_activate, + "on_menuitem_remove_torrentfile_activate": \ + self.on_menuitem_remove_torrentfile_activate, + "on_menuitem_remove_data_activate": \ + self.on_menuitem_remove_data_activate, + "on_menuitem_remove_both_activate": \ + self.on_menuitem_remove_both_activate, + + "on_menuitem_recheck_activate": self.on_menuitem_recheck_activate, + "on_menuitem_open_folder_activate": self.on_menuitem_open_folder_activate, + "on_menuitem_move_activate": self.on_menuitem_move_activate, + "on_menuitem_queue_top_activate": self.on_menuitem_queue_top_activate, + "on_menuitem_queue_up_activate": self.on_menuitem_queue_up_activate, + "on_menuitem_queue_down_activate": self.on_menuitem_queue_down_activate, + "on_menuitem_queue_bottom_activate": self.on_menuitem_queue_bottom_activate, + + }) + + self.change_sensitivity = [ + "menuitem_addtorrent" + ] + + if self.config["classic_mode"]: + # We need to remove the 'quit and shutdown daemon' menu item + self.window.main_glade.get_widget("menuitem_quitdaemon").hide() + self.window.main_glade.get_widget("separatormenuitem").hide() + self.window.main_glade.get_widget("menuitem_connectionmanager").hide() + + def start(self): + for widget in self.change_sensitivity: + self.window.main_glade.get_widget(widget).set_sensitive(True) + + # Hide the Open Folder menuitem and separator if not connected to a + # localhost. + non_remote_items = [ + "menuitem_open_folder", + "separator4" + ] + if not client.is_localhost(): + for widget in non_remote_items: + self.torrentmenu_glade.get_widget(widget).hide() + self.torrentmenu_glade.get_widget(widget).set_no_show_all(True) + else: + for widget in non_remote_items: + self.torrentmenu_glade.get_widget(widget).set_no_show_all(False) + + # Show the Torrent menu because we're connected to a host + self.menu_torrent.show() + + if not self.config["classic_mode"]: + self.window.main_glade.get_widget("separatormenuitem").show() + self.window.main_glade.get_widget("menuitem_quitdaemon").show() + + def stop(self): + for widget in self.change_sensitivity: + self.window.main_glade.get_widget(widget).set_sensitive(False) + + # Hide the Torrent menu + self.menu_torrent.hide() + + self.window.main_glade.get_widget("separatormenuitem").hide() + self.window.main_glade.get_widget("menuitem_quitdaemon").hide() + + def update_menu(self): + selected = component.get('TorrentView').get_selected_torrents() + if not selected or len(selected) == 0: + # No torrent is selected. Disable the 'Torrents' menu + self.menu_torrent.set_sensitive(False) + return + + self.menu_torrent.set_sensitive(True) + # XXX: Should also update Pause/Resume/Remove menuitems. + # Any better way than duplicating toolbar.py:update_buttons in here? + + def add_torrentmenu_separator(self): + sep = gtk.SeparatorMenuItem() + self.torrentmenu.append(sep) + sep.show() + return sep + + ### Callbacks ### + + ## File Menu ## + def on_menuitem_addtorrent_activate(self, data=None): + log.debug("on_menuitem_addtorrent_activate") + component.get("AddTorrentDialog").show() + + def on_menuitem_quitdaemon_activate(self, data=None): + log.debug("on_menuitem_quitdaemon_activate") + # Tell the core to shutdown + client.shutdown() + self.window.quit() + + def on_menuitem_quit_activate(self, data=None): + log.debug("on_menuitem_quit_activate") + if self.config["classic_mode"]: + try: + client.shutdown() + except deluge.error.NoCoreError: + pass + self.window.quit() + + ## Edit Menu ## + def on_menuitem_preferences_activate(self, data=None): + log.debug("on_menuitem_preferences_activate") + component.get("Preferences").show() + + def on_menuitem_connectionmanager_activate(self, data=None): + log.debug("on_menuitem_connectionmanager_activate") + component.get("ConnectionManager").show() + + ## Torrent Menu ## + def on_menuitem_pause_activate(self, data=None): + log.debug("on_menuitem_pause_activate") + client.pause_torrent( + component.get("TorrentView").get_selected_torrents()) + + def on_menuitem_resume_activate(self, data=None): + log.debug("on_menuitem_resume_activate") + client.resume_torrent( + component.get("TorrentView").get_selected_torrents()) + + def on_menuitem_updatetracker_activate(self, data=None): + log.debug("on_menuitem_updatetracker_activate") + client.force_reannounce( + component.get("TorrentView").get_selected_torrents()) + + def on_menuitem_edittrackers_activate(self, data=None): + log.debug("on_menuitem_edittrackers_activate") + from edittrackersdialog import EditTrackersDialog + dialog = EditTrackersDialog( + component.get("TorrentView").get_selected_torrent(), + component.get("MainWindow").window) + dialog.run() + + def on_menuitem_remove_session_activate(self, data=None): + log.debug("on_menuitem_remove_session_activate") + from removetorrentdialog import RemoveTorrentDialog + RemoveTorrentDialog( + component.get("TorrentView").get_selected_torrents()).run() + + def on_menuitem_remove_torrentfile_activate(self, data=None): + log.debug("on_menuitem_remove_torrentfile_activate") + from removetorrentdialog import RemoveTorrentDialog + RemoveTorrentDialog( + component.get("TorrentView").get_selected_torrents(), + remove_torrentfile=True).run() + + def on_menuitem_remove_data_activate(self, data=None): + log.debug("on_menuitem_remove_data_activate") + from removetorrentdialog import RemoveTorrentDialog + RemoveTorrentDialog( + component.get("TorrentView").get_selected_torrents(), + remove_data=True).run() + + def on_menuitem_remove_both_activate(self, data=None): + log.debug("on_menuitem_remove_both_activate") + from removetorrentdialog import RemoveTorrentDialog + RemoveTorrentDialog( + component.get("TorrentView").get_selected_torrents(), + remove_torrentfile=True, + remove_data=True).run() + + def on_menuitem_recheck_activate(self, data=None): + log.debug("on_menuitem_recheck_activate") + client.force_recheck( + component.get("TorrentView").get_selected_torrents()) + + def on_menuitem_open_folder_activate(self, data=None): + log.debug("on_menuitem_open_folder") + + def on_menuitem_move_activate(self, data=None): + log.debug("on_menuitem_move_activate") + if client.is_localhost(): + from deluge.configmanager import ConfigManager + config = ConfigManager("gtkui.conf") + chooser = gtk.FileChooserDialog(_("Choose a directory to move files to"\ + ) , component.get("MainWindow").window, \ + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, buttons=(gtk.STOCK_CANCEL, \ + gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) + if not common.windows_check(): + chooser.set_icon(common.get_logo(18)) + chooser.set_property("skip-taskbar-hint", True) + chooser.set_current_folder(config["choose_directory_dialog_path"]) + if chooser.run() == gtk.RESPONSE_OK: + result = chooser.get_filename() + config["choose_directory_dialog_path"] = result + client.move_storage( + component.get("TorrentView").get_selected_torrents(), result) + chooser.destroy() + else: + client.get_torrent_status(self.show_move_storage_dialog, component.get("TorrentView").get_selected_torrent(), ["save_path"]) + client.force_call(False) + + def show_move_storage_dialog(self, status): + log.debug("show_move_storage_dialog") + glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/move_storage_dialog.glade")) + dialog = glade.get_widget("move_storage_dialog") + dialog.set_transient_for(self.window.window) + entry = glade.get_widget("entry_destination") + entry.set_text(status["save_path"]) + def _on_response_event(widget, response_id): + log.debug("Moving torrents to %s", entry.get_text()) + path = entry.get_text() + client.move_storage(component.get("TorrentView").get_selected_torrents(), path) + dialog.hide() + dialog.connect("response", _on_response_event) + dialog.show() + + def on_menuitem_queue_top_activate(self, value): + log.debug("on_menuitem_queue_top_activate") + client.queue_top(None, component.get("TorrentView").get_selected_torrents()) + + def on_menuitem_queue_up_activate(self, value): + log.debug("on_menuitem_queue_up_activate") + client.queue_up(None, component.get("TorrentView").get_selected_torrents()) + + def on_menuitem_queue_down_activate(self, value): + log.debug("on_menuitem_queue_down_activate") + client.queue_down(None, component.get("TorrentView").get_selected_torrents()) + + def on_menuitem_queue_bottom_activate(self, value): + log.debug("on_menuitem_queue_bottom_activate") + client.queue_bottom(None, component.get("TorrentView").get_selected_torrents()) + + ## View Menu ## + def on_menuitem_toolbar_toggled(self, value): + log.debug("on_menuitem_toolbar_toggled") + component.get("ToolBar").visible(value.get_active()) + + def on_menuitem_labels_toggled(self, value): + log.debug("on_menuitem_labels_toggled") + component.get("SideBar").visible(value.get_active()) + + def on_menuitem_statusbar_toggled(self, value): + log.debug("on_menuitem_statusbar_toggled") + component.get("StatusBar").visible(value.get_active()) + + ## Help Menu ## + def on_menuitem_homepage_activate(self, data=None): + log.debug("on_menuitem_homepage_activate") + common.open_url_in_browser("http://deluge-torrent.org") + + def on_menuitem_faq_activate(self, data=None): + log.debug("on_menuitem_faq_activate") + common.open_url_in_browser("http://dev.deluge-torrent.org/wiki/Faq") + + def on_menuitem_community_activate(self, data=None): + log.debug("on_menuitem_community_activate") + common.open_url_in_browser("http://forum.deluge-torrent.org/") + + def on_menuitem_about_activate(self, data=None): + log.debug("on_menuitem_about_activate") + from aboutdialog import AboutDialog + AboutDialog().run() + + def on_menuitem_set_unlimited(self, widget): + log.debug("widget.name: %s", widget.name) + funcs = { + "menuitem_down_speed": client.set_torrent_max_download_speed, + "menuitem_up_speed": client.set_torrent_max_upload_speed, + "menuitem_max_connections": client.set_torrent_max_connections, + "menuitem_upload_slots": client.set_torrent_max_upload_slots + } + if widget.name in funcs.keys(): + for torrent in component.get("TorrentView").get_selected_torrents(): + funcs[widget.name](torrent, -1) + + def on_menuitem_set_other(self, widget): + log.debug("widget.name: %s", widget.name) + funcs = { + "menuitem_down_speed": client.set_torrent_max_download_speed, + "menuitem_up_speed": client.set_torrent_max_upload_speed, + "menuitem_max_connections": client.set_torrent_max_connections, + "menuitem_upload_slots": client.set_torrent_max_upload_slots + } + dialog_glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/dgtkpopups.glade")) + speed_dialog = dialog_glade.get_widget("speed_dialog") + spin_title = dialog_glade.get_widget("spin_title") + if widget.name == "menuitem_down_speed": + spin_title.set_text(_("Set Max Download Speed (KiB/s):")) + elif widget.name == "menuitem_up_speed": + spin_title.set_text(_("Set Max Upload Speed (KiB/s):")) + elif widget.name == "menuitem_max_connections": + spin_title.set_text(_("Set Max Connections:")) + elif widget.name == "menuitem_upload_slots": + spin_title.set_text(_("Set Max Upload Slots:")) + + spin_speed = dialog_glade.get_widget("spin_speed") + spin_speed.set_value(-1) + spin_speed.select_region(0, -1) + response = speed_dialog.run() + if response == 1: # OK Response + if widget.name == "menuitem_down_speed" or widget.name == "menuitem_up_speed": + value = spin_speed.get_value() + else: + value = spin_speed.get_value_as_int() + else: + speed_dialog.destroy() + return + speed_dialog.destroy() + if widget.name in funcs.keys(): + for torrent in component.get("TorrentView").get_selected_torrents(): + funcs[widget.name](torrent, value) + + def on_menuitem_set_automanaged_on(self, widget): + for torrent in component.get("TorrentView").get_selected_torrents(): + client.set_torrent_auto_managed(torrent, True) + + def on_menuitem_set_automanaged_off(self, widget): + for torrent in component.get("TorrentView").get_selected_torrents(): + client.set_torrent_auto_managed(torrent, False) diff --git a/deluge/ui/gtkui/options_tab.py b/deluge/ui/gtkui/options_tab.py new file mode 100644 index 000000000..596a01a04 --- /dev/null +++ b/deluge/ui/gtkui/options_tab.py @@ -0,0 +1,154 @@ +# +# options_tab.py +# +# Copyright (C) 2008 Andrew Resch ('andar') +# +# 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 2 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 deluge.component as component +from deluge.ui.client import aclient as client +from deluge.ui.gtkui.torrentdetails import Tab + +class OptionsTab(Tab): + def __init__(self): + glade = component.get("MainWindow").get_glade() + + self._name = "Options" + self._child_widget = glade.get_widget("options_tab") + self._tab_label = glade.get_widget("options_tab_label") + + self.spin_max_download = glade.get_widget("spin_max_download") + self.spin_max_upload = glade.get_widget("spin_max_upload") + self.spin_max_connections = glade.get_widget("spin_max_connections") + self.spin_max_upload_slots = glade.get_widget("spin_max_upload_slots") + self.chk_private = glade.get_widget("chk_private") + self.chk_prioritize_first_last = glade.get_widget("chk_prioritize_first_last") + self.chk_auto_managed = glade.get_widget("chk_auto_managed") + self.chk_stop_at_ratio = glade.get_widget("chk_stop_at_ratio") + self.chk_remove_at_ratio = glade.get_widget("chk_remove_at_ratio") + self.spin_stop_ratio = glade.get_widget("spin_stop_ratio") + + self.prev_torrent_id = None + self.prev_status = None + + glade.signal_autoconnect({ + "on_button_apply_clicked": self._on_button_apply_clicked, + "on_button_edit_trackers_clicked": self._on_button_edit_trackers_clicked + }) + + def update(self): + # Get the first selected torrent + torrent_id = component.get("TorrentView").get_selected_torrents() + + # Only use the first torrent in the list or return if None selected + if len(torrent_id) != 0: + torrent_id = torrent_id[0] + self._child_widget.set_sensitive(True) + else: + # No torrent is selected in the torrentview + self._child_widget.set_sensitive(False) + return + + if torrent_id != self.prev_torrent_id: + self.prev_status = None + + client.get_torrent_status(self._on_get_torrent_status, torrent_id, + ["max_download_speed", + "max_upload_speed", + "max_connections", + "max_upload_slots", + "private", + "prioritize_first_last", + "is_auto_managed", + "stop_at_ratio", + "stop_ratio", + "remove_at_ratio"]) + self.prev_torrent_id = torrent_id + + def clear(self): + self.prev_torrent_id = None + self.prev_status = None + + def _on_get_torrent_status(self, status): + # We only want to update values that have been applied in the core. This + # is so we don't overwrite the user changes that haven't been applied yet. + if self.prev_status == None: + self.prev_status = {}.fromkeys(status.keys(), None) + + if status != self.prev_status: + if status["max_download_speed"] != self.prev_status["max_download_speed"]: + self.spin_max_download.set_value(status["max_download_speed"]) + if status["max_upload_speed"] != self.prev_status["max_upload_speed"]: + self.spin_max_upload.set_value(status["max_upload_speed"]) + if status["max_connections"] != self.prev_status["max_connections"]: + self.spin_max_connections.set_value(status["max_connections"]) + if status["max_upload_slots"] != self.prev_status["max_upload_slots"]: + self.spin_max_upload_slots.set_value(status["max_upload_slots"]) + if status["private"] != self.prev_status["private"]: + self.chk_private.set_active(status["private"]) + if status["prioritize_first_last"] != self.prev_status["prioritize_first_last"]: + self.chk_prioritize_first_last.set_active(status["prioritize_first_last"]) + if status["is_auto_managed"] != self.prev_status["is_auto_managed"]: + self.chk_auto_managed.set_active(status["is_auto_managed"]) + if status["stop_at_ratio"] != self.prev_status["stop_at_ratio"]: + self.chk_stop_at_ratio.set_active(status["stop_at_ratio"]) + if status["stop_ratio"] != self.prev_status["stop_ratio"]: + self.spin_stop_ratio.set_value(status["stop_ratio"]) + if status["remove_at_ratio"] != self.prev_status["remove_at_ratio"]: + self.chk_remove_at_ratio.set_active(status["remove_at_ratio"]) + + self.prev_status = status + + def _on_button_apply_clicked(self, button): + if self.spin_max_download.get_value() != self.prev_status["max_download_speed"]: + client.set_torrent_max_download_speed(self.prev_torrent_id, self.spin_max_download.get_value()) + if self.spin_max_upload.get_value() != self.prev_status["max_upload_speed"]: + client.set_torrent_max_upload_speed(self.prev_torrent_id, self.spin_max_upload.get_value()) + if self.spin_max_connections.get_value_as_int() != self.prev_status["max_connections"]: + client.set_torrent_max_connections(self.prev_torrent_id, self.spin_max_connections.get_value_as_int()) + if self.spin_max_upload_slots.get_value_as_int() != self.prev_status["max_upload_slots"]: + client.set_torrent_max_upload_slots(self.prev_torrent_id, self.spin_max_upload_slots.get_value_as_int()) + if self.chk_prioritize_first_last.get_active() != self.prev_status["prioritize_first_last"]: + client.set_torrent_prioritize_first_last(self.prev_torrent_id, self.chk_prioritize_first_last.get_active()) + if self.chk_auto_managed.get_active() != self.prev_status["is_auto_managed"]: + client.set_torrent_auto_managed(self.prev_torrent_id, self.chk_auto_managed.get_active()) + if self.chk_stop_at_ratio.get_active() != self.prev_status["stop_at_ratio"]: + client.set_torrent_stop_at_ratio(self.prev_torrent_id, self.chk_stop_at_ratio.get_active()) + if self.spin_stop_ratio.get_value() != self.prev_status["stop_ratio"]: + client.set_torrent_stop_ratio(self.prev_torrent_id, self.spin_stop_ratio.get_value()) + if self.chk_remove_at_ratio.get_active() != self.prev_status["remove_at_ratio"]: + client.set_torrent_remove_at_ratio(self.prev_torrent_id, self.chk_remove_at_ratio.get_active()) + + + def _on_button_edit_trackers_clicked(self, button): + from edittrackersdialog import EditTrackersDialog + dialog = EditTrackersDialog( + self.prev_torrent_id, + component.get("MainWindow").window) + dialog.run() diff --git a/deluge/ui/gtkui/peers_tab.py b/deluge/ui/gtkui/peers_tab.py new file mode 100644 index 000000000..5bdae9570 --- /dev/null +++ b/deluge/ui/gtkui/peers_tab.py @@ -0,0 +1,300 @@ +# +# peers_tab.py +# +# Copyright (C) 2008 Andrew Resch ('andar') +# +# 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 2 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, gtk.glade +import os.path +import cPickle +import pkg_resources +import gobject +from itertools import izip + +from deluge.ui.client import aclient as client +from deluge.configmanager import ConfigManager +import deluge.component as component +import deluge.common +from deluge.ui.gtkui.listview import cell_data_speed as cell_data_speed +from deluge.ui.gtkui.torrentdetails import Tab +from deluge.log import LOG as log + +class ColumnState: + def __init__(self, name, position, width, sort, sort_order): + self.name = name + self.position = position + self.width = width + self.sort = sort + self.sort_order = sort_order + +class PeersTab(Tab): + def __init__(self): + glade = component.get("MainWindow").get_glade() + + self._name = "Peers" + self._child_widget = glade.get_widget("peers_tab") + self._tab_label = glade.get_widget("peers_tab_label") + + self.listview = glade.get_widget("peers_listview") + # country pixbuf, ip, client, downspeed, upspeed, country code, int_ip, seed/peer icon + self.liststore = gtk.ListStore(gtk.gdk.Pixbuf, str, str, int, int, str, gobject.TYPE_UINT, gtk.gdk.Pixbuf) + self.cached_flag_pixbufs = {} + + self.seed_pixbuf = gtk.gdk.pixbuf_new_from_file(deluge.common.get_pixmap("seeding16.png")) + self.peer_pixbuf = gtk.gdk.pixbuf_new_from_file(deluge.common.get_pixmap("downloading16.png")) + + # key is ip address, item is row iter + self.peers = {} + + # Country column + column = gtk.TreeViewColumn() + render = gtk.CellRendererPixbuf() + column.pack_start(render, False) + column.add_attribute(render, "pixbuf", 0) + column.set_sort_column_id(5) + column.set_clickable(True) + column.set_resizable(True) + column.set_expand(False) + column.set_min_width(10) + column.set_reorderable(True) + self.listview.append_column(column) + + # Address column + column = gtk.TreeViewColumn(_("Address")) + render = gtk.CellRendererPixbuf() + column.pack_start(render, False) + column.add_attribute(render, "pixbuf", 7) + render = gtk.CellRendererText() + column.pack_start(render, False) + column.add_attribute(render, "text", 1) + column.set_sort_column_id(6) + column.set_clickable(True) + column.set_resizable(True) + column.set_expand(False) + column.set_min_width(10) + column.set_reorderable(True) + self.listview.append_column(column) + + # Client column + column = gtk.TreeViewColumn(_("Client")) + render = gtk.CellRendererText() + column.pack_start(render, False) + column.add_attribute(render, "text", 2) + column.set_sort_column_id(2) + column.set_clickable(True) + column.set_resizable(True) + column.set_expand(False) + column.set_min_width(10) + column.set_reorderable(True) + self.listview.append_column(column) + + # Down Speed column + column = gtk.TreeViewColumn(_("Down Speed")) + render = gtk.CellRendererText() + column.pack_start(render, False) + column.set_cell_data_func(render, cell_data_speed, 3) + column.set_sort_column_id(3) + column.set_clickable(True) + column.set_resizable(True) + column.set_expand(False) + column.set_min_width(10) + column.set_reorderable(True) + self.listview.append_column(column) + + # Up Speed column + column = gtk.TreeViewColumn(_("Up Speed")) + render = gtk.CellRendererText() + column.pack_start(render, False) + column.set_cell_data_func(render, cell_data_speed, 4) + column.set_sort_column_id(4) + column.set_clickable(True) + column.set_resizable(True) + column.set_expand(False) + column.set_min_width(10) + column.set_reorderable(True) + self.listview.append_column(column) + + self.listview.set_model(self.liststore) + + self.load_state() + + self.torrent_id = None + + def save_state(self): + filename = "peers_tab.state" + state = [] + for index, column in enumerate(self.listview.get_columns()): + state.append(ColumnState(column.get_title(), index, column.get_width(), + column.get_sort_indicator(), int(column.get_sort_order()))) + + # Get the config location for saving the state file + config_location = ConfigManager("gtkui.conf")["config_location"] + + try: + log.debug("Saving FilesTab state file: %s", filename) + state_file = open(os.path.join(config_location, filename), "wb") + cPickle.dump(state, state_file) + state_file.close() + except IOError, e: + log.warning("Unable to save state file: %s", e) + + def load_state(self): + filename = "peers_tab.state" + # Get the config location for loading the state file + config_location = ConfigManager("gtkui.conf")["config_location"] + state = None + + try: + log.debug("Loading PeersTab state file: %s", filename) + state_file = open(os.path.join(config_location, filename), "rb") + state = cPickle.load(state_file) + state_file.close() + except (EOFError, IOError), e: + log.warning("Unable to load state file: %s", e) + + if state == None: + return + + if len(state) != len(self.listview.get_columns()): + log.warning("peers_tab.state is not compatible! rejecting..") + return + + for column_state in state: + # Find matching columns in the listview + for (index, column) in enumerate(self.listview.get_columns()): + if column_state.name == column.get_title(): + # We have a match, so set options that were saved in state + if column_state.width > 0: + column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + column.set_fixed_width(column_state.width) + column.set_sort_indicator(column_state.sort) + column.set_sort_order(column_state.sort_order) + if column_state.position != index: + # Column is in wrong position + if column_state.position == 0: + self.listview.move_column_after(column, None) + else: + self.listview.move_column_after(column, self.listview.get_columns()[column_state.position - 1]) + + def update(self): + # Get the first selected torrent + torrent_id = component.get("TorrentView").get_selected_torrents() + + # Only use the first torrent in the list or return if None selected + if len(torrent_id) != 0: + torrent_id = torrent_id[0] + else: + # No torrent is selected in the torrentview + self.liststore.clear() + return + + if torrent_id != self.torrent_id: + # We only want to do this if the torrent_id has changed + self.liststore.clear() + self.peers = {} + self.torrent_id = torrent_id + + client.get_torrent_status(self._on_get_torrent_status, torrent_id, ["peers"]) + + def get_flag_pixbuf(self, country): + if country == " ": + return None + + if not self.cached_flag_pixbufs.has_key(country): + # We haven't created a pixbuf for this country yet + try: + self.cached_flag_pixbufs[country] = gtk.gdk.pixbuf_new_from_file( + pkg_resources.resource_filename( + "deluge", + os.path.join("data", "pixmaps", "flags", country.lower() + ".png"))) + except Exception, e: + log.debug("Unable to load flag: %s", e) + return None + + return self.cached_flag_pixbufs[country] + + def _on_get_torrent_status(self, status): + new_ips = set() + for peer in status["peers"]: + new_ips.add(peer["ip"]) + if self.peers.has_key(peer["ip"]): + # We already have this peer in our list, so lets just update it + row = self.peers[peer["ip"]] + if not self.liststore.iter_is_valid(row): + # This iter is invalid, delete it and continue to next iteration + del self.peers[peer["ip"]] + continue + values = self.liststore.get(row, 3, 4, 5, 7) + if peer["down_speed"] != values[0]: + self.liststore.set_value(row, 3, peer["down_speed"]) + if peer["up_speed"] != values[1]: + self.liststore.set_value(row, 4, peer["up_speed"]) + if peer["country"] != values[2]: + self.liststore.set_value(row, 5, peer["country"]) + self.liststore.set_value(row, 0, self.get_flag_pixbuf(peer["country"])) + if peer["seed"]: + icon = self.seed_pixbuf + else: + icon = self.peer_pixbuf + + if icon != values[3]: + self.liststore.set_value(row, 7, icon) + + else: + # Peer is not in list so we need to add it + + # Create an int IP address for sorting purposes + ip_int = sum([int(byte) << shift + for byte, shift in izip(peer["ip"].split(":")[0].split("."), (24, 16, 8, 0))]) + + if peer["seed"]: + icon = self.seed_pixbuf + else: + icon = self.peer_pixbuf + + row = self.liststore.append([ + self.get_flag_pixbuf(peer["country"]), + peer["ip"], + peer["client"], + peer["down_speed"], + peer["up_speed"], + peer["country"], + ip_int, + icon]) + + self.peers[peer["ip"]] = row + + # Now we need to remove any ips that were not in status["peers"] list + for ip in set(self.peers.keys()).difference(new_ips): + self.liststore.remove(self.peers[ip]) + del self.peers[ip] + + def clear(self): + self.liststore.clear() diff --git a/deluge/ui/gtkui/pluginmanager.py b/deluge/ui/gtkui/pluginmanager.py new file mode 100644 index 000000000..324ddc68d --- /dev/null +++ b/deluge/ui/gtkui/pluginmanager.py @@ -0,0 +1,137 @@ +# +# pluginmanager.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 deluge.component as component +import deluge.pluginmanagerbase +from deluge.ui.client import aclient as client +from deluge.configmanager import ConfigManager +from deluge.log import LOG as log + +class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, + component.Component): + def __init__(self): + component.Component.__init__(self, "PluginManager", depend=["Signals"]) + self.config = ConfigManager("gtkui.conf") + deluge.pluginmanagerbase.PluginManagerBase.__init__( + self, "gtkui.conf", "deluge.plugin.gtkui") + + self.hooks = { + "on_apply_prefs": [], + "on_show_prefs": [] + } + + def register_hook(self, hook, function): + """Register a hook function with the plugin manager""" + try: + self.hooks[hook].append(function) + except KeyError: + log.warning("Plugin attempting to register invalid hook.") + + def deregister_hook(self, hook, function): + """Deregisters a hook function""" + try: + self.hooks[hook].remove(function) + except: + log.warning("Unable to deregister hook %s", hook) + + def start(self): + """Start the plugin manager""" + # Update the enabled_plugins from the core + client.get_enabled_plugins(self._on_get_enabled_plugins) + + def stop(self): + # Disable the plugins + self.disable_plugins() + + def _on_get_enabled_plugins(self, enabled_plugins): + log.debug("Core has these plugins enabled: %s", enabled_plugins) + self.config["enabled_plugins"] = enabled_plugins + + # Enable the plugins that are enabled in the config and core + self.enable_plugins() + + ## Hook functions + def run_on_show_prefs(self): + """This hook is run before the user is shown the preferences dialog. + It is designed so that plugins can update their preference page with + the config.""" + log.debug("run_on_show_prefs") + for function in self.hooks["on_show_prefs"]: + function() + + def run_on_apply_prefs(self): + """This hook is run after the user clicks Apply or OK in the preferences + dialog. + """ + log.debug("run_on_apply_prefs") + for function in self.hooks["on_apply_prefs"]: + function() + + ## Plugin functions.. will likely move to own class.. + + def add_torrentview_text_column(self, *args, **kwargs): + return component.get("TorrentView").add_text_column(*args, **kwargs) + + def remove_torrentview_column(self, *args): + return component.get("TorrentView").remove_column(*args) + + def add_toolbar_separator(self): + return component.get("ToolBar").add_separator() + + def add_toolbar_button(self, *args, **kwargs): + return component.get("ToolBar").add_toolbutton(*args, **kwargs) + + def remove_toolbar_button(self, *args): + return component.get("ToolBar").remove(*args) + + def add_torrentmenu_menu(self, *args): + return component.get("MenuBar").torrentmenu.append(*args) + + def add_torrentmenu_separator(self): + return component.get("MenuBar").add_torrentmenu_separator() + + def remove_torrentmenu_item(self, *args): + return component.get("MenuBar").torrentmenu.remove(*args) + + def add_preferences_page(self, *args): + return component.get("Preferences").add_page(*args) + + def remove_preferences_page(self, *args): + return component.get("Preferences").remove_page(*args) + + def update_torrent_view(self, *args): + return component.get("TorrentView").update(*args) + + def get_selected_torrents(self): + """Returns a list of the selected torrent_ids""" + return component.get("TorrentView").get_selected_torrents() diff --git a/deluge/ui/gtkui/preferences.py b/deluge/ui/gtkui/preferences.py new file mode 100644 index 000000000..2a7dc3d07 --- /dev/null +++ b/deluge/ui/gtkui/preferences.py @@ -0,0 +1,683 @@ +# +# preferences.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 pygtk +pygtk.require('2.0') +import gtk, gtk.glade +import pkg_resources + +import deluge.component as component +from deluge.log import LOG as log +from deluge.ui.client import aclient as client +import deluge.common +import deluge.error +from deluge.configmanager import ConfigManager + +class Preferences(component.Component): + def __init__(self): + component.Component.__init__(self, "Preferences") + self.window = component.get("MainWindow") + self.glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/preferences_dialog.glade")) + self.pref_dialog = self.glade.get_widget("pref_dialog") + self.pref_dialog.set_icon(deluge.common.get_logo(32)) + self.treeview = self.glade.get_widget("treeview") + self.notebook = self.glade.get_widget("notebook") + self.gtkui_config = ConfigManager("gtkui.conf") + # Setup the liststore for the categories (tab pages) + self.liststore = gtk.ListStore(int, str) + self.treeview.set_model(self.liststore) + render = gtk.CellRendererText() + column = gtk.TreeViewColumn("Categories", render, text=1) + self.treeview.append_column(column) + # Add the default categories + i = 0 + for category in ["Downloads", "Network", "Bandwidth", "Interface", + "Other", "Daemon", "Queue", "Plugins"]: + self.liststore.append([i, category]) + i += 1 + + # Setup plugin tab listview + self.plugin_liststore = gtk.ListStore(str, bool) + self.plugin_listview = self.glade.get_widget("plugin_listview") + self.plugin_listview.set_model(self.plugin_liststore) + render = gtk.CellRendererToggle() + render.connect("toggled", self.on_plugin_toggled) + render.set_property("activatable", True) + self.plugin_listview.append_column( + gtk.TreeViewColumn(_("Enabled"), render, active=1)) + self.plugin_listview.append_column( + gtk.TreeViewColumn(_("Plugin"), gtk.CellRendererText(), text=0)) + + # Connect to the 'changed' event of TreeViewSelection to get selection + # changes. + self.treeview.get_selection().connect("changed", + self.on_selection_changed) + + self.plugin_listview.get_selection().connect("changed", + self.on_plugin_selection_changed) + + self.glade.signal_autoconnect({ + "on_pref_dialog_delete_event": self.on_pref_dialog_delete_event, + "on_button_ok_clicked": self.on_button_ok_clicked, + "on_button_apply_clicked": self.on_button_apply_clicked, + "on_button_cancel_clicked": self.on_button_cancel_clicked, + "on_toggle": self.on_toggle, + "on_test_port_clicked": self.on_test_port_clicked + }) + + # These get updated by requests done to the core + self.all_plugins = [] + self.enabled_plugins = [] + + def __del__(self): + del self.gtkui_config + + def add_page(self, name, widget): + """Add a another page to the notebook""" + # Create a header and scrolled window for the preferences tab + widget.unparent() + vbox = gtk.VBox() + label = gtk.Label() + label.set_use_markup(True) + label.set_markup("" + name + "") + label.set_alignment(0.05, 0.50) + label.set_padding(0, 10) + vbox.pack_start(label, False, True, 0) + sep = gtk.HSeparator() + vbox.pack_start(sep, False, True, 0) + align = gtk.Alignment() + align.set_padding(5, 0, 0, 0) + align.add(widget) + vbox.pack_start(align, False, False, 0) + scrolled = gtk.ScrolledWindow() + viewport = gtk.Viewport() + viewport.set_shadow_type(gtk.SHADOW_NONE) + viewport.add(vbox) + scrolled.add(viewport) + scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + scrolled.show_all() + # Add this page to the notebook + index = self.notebook.append_page(scrolled) + self.liststore.append([index, name]) + return name + + def remove_page(self, name): + """Removes a page from the notebook""" + self.page_num_to_remove = None + self.iter_to_remove = None + + def check_row(model, path, iter, user_data): + row_name = model.get_value(iter, 1) + if row_name == user_data: + # This is the row we need to remove + self.page_num_to_remove = model.get_value(iter, 0) + self.iter_to_remove = iter + return + + self.liststore.foreach(check_row, name) + # Remove the page and row + if self.page_num_to_remove != None: + self.notebook.remove_page(self.page_num_to_remove) + if self.iter_to_remove != None: + self.liststore.remove(self.iter_to_remove) + + def _on_get_config(self, config): + self.core_config = config + + def _on_get_available_plugins(self, plugins): + self.all_plugins = plugins + + def _on_get_enabled_plugins(self, plugins): + self.enabled_plugins = plugins + + def _on_get_listen_port(self, port): + self.active_port = port + + def show(self, page=None): + """Page should be the string in the left list.. ie, 'Network' or 'Bandwidth'""" + if page != None: + for (index, string) in self.liststore: + if page == string: + self.treeview.get_selection().select_path(index) + break + + # Update the preferences dialog to reflect current config settings + self.core_config = {} + try: + client.get_config(self._on_get_config) + client.get_available_plugins(self._on_get_available_plugins) + client.get_enabled_plugins(self._on_get_enabled_plugins) + client.get_listen_port(self._on_get_listen_port) + # Force these calls and block until we've done them all + client.force_call() + except deluge.error.NoCoreError: + log.debug("Not connected to a daemon..") + + if self.core_config != {} and self.core_config != None: + core_widgets = { + "download_path_button": \ + ("filename", self.core_config["download_location"]), + "chk_move_completed": \ + ("active", self.core_config["move_completed"]), + "move_completed_path_button": \ + ("filename", self.core_config["move_completed_path"]), + "chk_copy_torrent_file": \ + ("active", self.core_config["copy_torrent_file"]), + "torrent_files_button": \ + ("filename", self.core_config["torrentfiles_location"]), + "chk_autoadd": \ + ("active", self.core_config["autoadd_enable"]), + "folder_autoadd": \ + ("filename", self.core_config["autoadd_location"]), + "radio_compact_allocation": \ + ("active", self.core_config["compact_allocation"]), + "radio_full_allocation": \ + ("not_active", self.core_config["compact_allocation"]), + "chk_prioritize_first_last_pieces": \ + ("active", + self.core_config["prioritize_first_last_pieces"]), + "spin_port_min": ("value", self.core_config["listen_ports"][0]), + "spin_port_max": ("value", self.core_config["listen_ports"][1]), + "active_port_label": ("text", str(self.active_port)), + "chk_random_port": ("active", self.core_config["random_port"]), + "chk_dht": ("active", self.core_config["dht"]), + "chk_upnp": ("active", self.core_config["upnp"]), + "chk_natpmp": ("active", self.core_config["natpmp"]), + "chk_utpex": ("active", self.core_config["utpex"]), + "chk_lsd": ("active", self.core_config["lsd"]), + "chk_new_releases": ("active", self.core_config["new_release_check"]), + "chk_send_info": ("active", self.core_config["send_info"]), + "combo_encin": ("active", self.core_config["enc_in_policy"]), + "combo_encout": ("active", self.core_config["enc_out_policy"]), + "combo_enclevel": ("active", self.core_config["enc_level"]), + "chk_pref_rc4": ("active", self.core_config["enc_prefer_rc4"]), + "spin_max_connections_global": \ + ("value", self.core_config["max_connections_global"]), + "spin_max_download": \ + ("value", self.core_config["max_download_speed"]), + "spin_max_upload": \ + ("value", self.core_config["max_upload_speed"]), + "spin_max_upload_slots_global": \ + ("value", self.core_config["max_upload_slots_global"]), + "spin_max_connections_per_torrent": \ + ("value", self.core_config["max_connections_per_torrent"]), + "spin_max_upload_slots_per_torrent": \ + ("value", self.core_config["max_upload_slots_per_torrent"]), + "spin_max_download_per_torrent": \ + ("value", self.core_config["max_download_speed_per_torrent"]), + "spin_max_upload_per_torrent": \ + ("value", self.core_config["max_upload_speed_per_torrent"]), + "spin_daemon_port": \ + ("value", self.core_config["daemon_port"]), + "chk_allow_remote_connections": \ + ("active", self.core_config["allow_remote"]), + "spin_active": ("value", self.core_config["max_active_limit"]), + "spin_seeding": ("value", self.core_config["max_active_seeding"]), + "spin_downloading": ("value", self.core_config["max_active_downloading"]), + "chk_dont_count_slow_torrents": ("active", self.core_config["dont_count_slow_torrents"]), + "chk_queue_new_top": ("active", self.core_config["queue_new_to_top"]), + "spin_share_ratio_limit": ("value", self.core_config["share_ratio_limit"]), + "spin_seed_time_ratio_limit": \ + ("value", self.core_config["seed_time_ratio_limit"]), + "spin_seed_time_limit": ("value", self.core_config["seed_time_limit"]), + "chk_seed_ratio": ("active", self.core_config["stop_seed_at_ratio"]), + "spin_share_ratio": ("value", self.core_config["stop_seed_ratio"]), + "chk_remove_ratio": ("active", self.core_config["remove_seed_at_ratio"]) + } + + # Change a few widgets if we're connected to a remote host + if not client.is_localhost(): + self.glade.get_widget("entry_download_path").show() + self.glade.get_widget("download_path_button").hide() + core_widgets.pop("download_path_button") + core_widgets["entry_download_path"] = ("text", self.core_config["download_location"]) + + self.glade.get_widget("entry_move_completed_path").show() + self.glade.get_widget("move_completed_path_button").hide() + core_widgets.pop("move_completed_path_button") + core_widgets["entry_move_completed_path"] = ("text", self.core_config["move_completed_path"]) + + self.glade.get_widget("entry_torrents_path").show() + self.glade.get_widget("torrent_files_button").hide() + core_widgets.pop("torrent_files_button") + core_widgets["entry_torrents_path"] = ("text", self.core_config["torrentfiles_location"]) + + self.glade.get_widget("entry_autoadd").show() + self.glade.get_widget("folder_autoadd").hide() + core_widgets.pop("folder_autoadd") + core_widgets["entry_autoadd"] = ("text", self.core_config["autoadd_location"]) + else: + self.glade.get_widget("entry_download_path").hide() + self.glade.get_widget("download_path_button").show() + self.glade.get_widget("entry_move_completed_path").hide() + self.glade.get_widget("move_completed_path_button").show() + self.glade.get_widget("entry_torrents_path").hide() + self.glade.get_widget("torrent_files_button").show() + self.glade.get_widget("entry_autoadd").hide() + self.glade.get_widget("folder_autoadd").show() + + # Update the widgets accordingly + for key in core_widgets.keys(): + modifier = core_widgets[key][0] + value = core_widgets[key][1] + widget = self.glade.get_widget(key) + if type(widget) == gtk.FileChooserButton: + for child in widget.get_children(): + child.set_sensitive(True) + widget.set_sensitive(True) + + if modifier == "filename": + if value: + try: + widget.set_current_folder(value) + except Exception, e: + log.debug("Unable to set_current_folder: %s", e) + elif modifier == "active": + widget.set_active(value) + elif modifier == "not_active": + widget.set_active(not value) + elif modifier == "value": + widget.set_value(value) + elif modifier == "text": + widget.set_text(value) + + for key in core_widgets.keys(): + widget = self.glade.get_widget(key) + # Update the toggle status if necessary + self.on_toggle(widget) + else: + core_widget_list = [ + "download_path_button", + "chk_move_completed", + "move_completed_path_button", + "chk_copy_torrent_file", + "torrent_files_button", + "chk_autoadd", + "folder_autoadd", + "radio_compact_allocation", + "radio_full_allocation", + "chk_prioritize_first_last_pieces", + "spin_port_min", + "spin_port_max", + "active_port_label", + "chk_random_port", + "chk_dht", + "chk_upnp", + "chk_natpmp", + "chk_utpex", + "chk_lsd", + "chk_send_info", + "chk_new_releases", + "combo_encin", + "combo_encout", + "combo_enclevel", + "chk_pref_rc4", + "spin_max_connections_global", + "spin_max_download", + "spin_max_upload", + "spin_max_upload_slots_global", + "spin_max_connections_per_torrent", + "spin_max_upload_slots_per_torrent", + "spin_max_download_per_torrent", + "spin_max_upload_per_torrent", + "spin_daemon_port", + "chk_allow_remote_connections", + "spin_seeding", + "spin_downloading", + "spin_active", + "chk_dont_count_slow_torrents", + "chk_queue_new_top", + "chk_seed_ratio", + "spin_share_ratio", + "chk_remove_ratio", + "spin_share_ratio_limit", + "spin_seed_time_ratio_limit", + "spin_seed_time_limit" + ] + # We don't appear to be connected to a daemon + for key in core_widget_list: + widget = self.glade.get_widget(key) + if type(widget) == gtk.FileChooserButton: + for child in widget.get_children(): + child.set_sensitive(False) + widget.set_sensitive(False) + + ## Downloads tab ## + self.glade.get_widget("chk_show_dialog").set_active( + self.gtkui_config["interactive_add"]) + self.glade.get_widget("chk_focus_dialog").set_active( + self.gtkui_config["focus_add_dialog"]) + + ## Interface tab ## + self.glade.get_widget("chk_use_tray").set_active( + self.gtkui_config["enable_system_tray"]) + self.glade.get_widget("chk_min_on_close").set_active( + self.gtkui_config["close_to_tray"]) + self.glade.get_widget("chk_start_in_tray").set_active( + self.gtkui_config["start_in_tray"]) + self.glade.get_widget("chk_lock_tray").set_active( + self.gtkui_config["lock_tray"]) + self.glade.get_widget("chk_classic_mode").set_active( + self.gtkui_config["classic_mode"]) + + ## Other tab ## + self.glade.get_widget("chk_show_new_releases").set_active( + self.gtkui_config["show_new_releases"]) + + ## Plugins tab ## + all_plugins = self.all_plugins + enabled_plugins = self.enabled_plugins + # Clear the existing list so we don't duplicate entries. + self.plugin_liststore.clear() + # Iterate through the lists and add them to the liststore + for plugin in all_plugins: + if plugin in enabled_plugins: + enabled = True + else: + enabled = False + row = self.plugin_liststore.append() + self.plugin_liststore.set_value(row, 0, plugin) + self.plugin_liststore.set_value(row, 1, enabled) + + component.get("PluginManager").run_on_show_prefs() + # Now show the dialog + self.pref_dialog.show() + + def set_config(self): + """Sets all altered config values in the core""" + import sha + # Get the values from the dialog + new_core_config = {} + new_gtkui_config = {} + + ## Downloads tab ## + new_gtkui_config["interactive_add"] = \ + self.glade.get_widget("chk_show_dialog").get_active() + new_gtkui_config["focus_add_dialog"] = \ + self.glade.get_widget("chk_focus_dialog").get_active() + new_core_config["copy_torrent_file"] = \ + self.glade.get_widget("chk_copy_torrent_file").get_active() + new_core_config["move_completed"] = \ + self.glade.get_widget("chk_move_completed").get_active() + if client.is_localhost(): + new_core_config["download_location"] = \ + self.glade.get_widget("download_path_button").get_filename() + new_core_config["move_completed_path"] = \ + self.glade.get_widget("move_completed_path_button").get_filename() + new_core_config["torrentfiles_location"] = \ + self.glade.get_widget("torrent_files_button").get_filename() + else: + new_core_config["download_location"] = \ + self.glade.get_widget("entry_download_path").get_text() + new_core_config["move_completed_path"] = \ + self.glade.get_widget("entry_move_completed_path").get_text() + new_core_config["torrentfiles_location"] = \ + self.glade.get_widget("entry_torrents_path").get_text() + + new_core_config["autoadd_enable"] = \ + self.glade.get_widget("chk_autoadd").get_active() + if client.is_localhost(): + new_core_config["autoadd_location"] = \ + self.glade.get_widget("folder_autoadd").get_filename() + else: + new_core_config["autoadd_location"] = \ + self.glade.get_widget("entry_autoadd").get_text() + + new_core_config["compact_allocation"] = \ + self.glade.get_widget("radio_compact_allocation").get_active() + new_core_config["prioritize_first_last_pieces"] = \ + self.glade.get_widget( + "chk_prioritize_first_last_pieces").get_active() + + ## Network tab ## + listen_ports = [] + listen_ports.append( + self.glade.get_widget("spin_port_min").get_value_as_int()) + listen_ports.append( + self.glade.get_widget("spin_port_max").get_value_as_int()) + new_core_config["listen_ports"] = listen_ports + new_core_config["random_port"] = \ + self.glade.get_widget("chk_random_port").get_active() + new_core_config["dht"] = self.glade.get_widget("chk_dht").get_active() + new_core_config["upnp"] = self.glade.get_widget("chk_upnp").get_active() + new_core_config["natpmp"] = \ + self.glade.get_widget("chk_natpmp").get_active() + new_core_config["utpex"] = \ + self.glade.get_widget("chk_utpex").get_active() + new_core_config["lsd"] = \ + self.glade.get_widget("chk_lsd").get_active() + new_core_config["enc_in_policy"] = \ + self.glade.get_widget("combo_encin").get_active() + new_core_config["enc_out_policy"] = \ + self.glade.get_widget("combo_encout").get_active() + new_core_config["enc_level"] = \ + self.glade.get_widget("combo_enclevel").get_active() + new_core_config["enc_prefer_rc4"] = \ + self.glade.get_widget("chk_pref_rc4").get_active() + + ## Bandwidth tab ## + new_core_config["max_connections_global"] = \ + self.glade.get_widget( + "spin_max_connections_global").get_value_as_int() + new_core_config["max_download_speed"] = \ + self.glade.get_widget("spin_max_download").get_value() + new_core_config["max_upload_speed"] = \ + self.glade.get_widget("spin_max_upload").get_value() + new_core_config["max_upload_slots_global"] = \ + self.glade.get_widget( + "spin_max_upload_slots_global").get_value_as_int() + new_core_config["max_connections_per_torrent"] = \ + self.glade.get_widget( + "spin_max_connections_per_torrent").get_value_as_int() + new_core_config["max_upload_slots_per_torrent"] = \ + self.glade.get_widget( + "spin_max_upload_slots_per_torrent").get_value_as_int() + new_core_config["max_upload_speed_per_torrent"] = \ + self.glade.get_widget( + "spin_max_upload_per_torrent").get_value() + new_core_config["max_download_speed_per_torrent"] = \ + self.glade.get_widget( + "spin_max_download_per_torrent").get_value() + + ## Interface tab ## + new_gtkui_config["enable_system_tray"] = \ + self.glade.get_widget("chk_use_tray").get_active() + new_gtkui_config["close_to_tray"] = \ + self.glade.get_widget("chk_min_on_close").get_active() + new_gtkui_config["start_in_tray"] = \ + self.glade.get_widget("chk_start_in_tray").get_active() + new_gtkui_config["lock_tray"] = \ + self.glade.get_widget("chk_lock_tray").get_active() + passhex = sha.new(self.glade.get_widget("txt_tray_password").get_text())\ + .hexdigest() + if passhex != "c07eb5a8c0dc7bb81c217b67f11c3b7a5e95ffd7": + new_gtkui_config["tray_password"] = passhex + new_gtkui_config["classic_mode"] = \ + self.glade.get_widget("chk_classic_mode").get_active() + + ## Other tab ## + new_gtkui_config["show_new_releases"] = \ + self.glade.get_widget("chk_show_new_releases").get_active() + new_core_config["send_info"] = \ + self.glade.get_widget("chk_send_info").get_active() + + ## Daemon tab ## + new_core_config["daemon_port"] = \ + self.glade.get_widget("spin_daemon_port").get_value_as_int() + new_core_config["allow_remote"] = \ + self.glade.get_widget("chk_allow_remote_connections").get_active() + new_core_config["new_release_check"] = \ + self.glade.get_widget("chk_new_releases").get_active() + + ## Queue tab ## + new_core_config["queue_new_to_top"] = \ + self.glade.get_widget("chk_queue_new_top").get_active() + new_core_config["max_active_seeding"] = \ + self.glade.get_widget("spin_seeding").get_value_as_int() + new_core_config["max_active_downloading"] = \ + self.glade.get_widget("spin_downloading").get_value_as_int() + new_core_config["max_active_limit"] = \ + self.glade.get_widget("spin_active").get_value_as_int() + new_core_config["dont_count_slow_torrents"] = \ + self.glade.get_widget("chk_dont_count_slow_torrents").get_active() + new_core_config["stop_seed_at_ratio"] = \ + self.glade.get_widget("chk_seed_ratio").get_active() + new_core_config["remove_seed_at_ratio"] = \ + self.glade.get_widget("chk_remove_ratio").get_active() + new_core_config["stop_seed_ratio"] = \ + self.glade.get_widget("spin_share_ratio").get_value() + new_core_config["share_ratio_limit"] = \ + self.glade.get_widget("spin_share_ratio_limit").get_value() + new_core_config["seed_time_ratio_limit"] = \ + self.glade.get_widget("spin_seed_time_ratio_limit").get_value() + new_core_config["seed_time_limit"] = \ + self.glade.get_widget("spin_seed_time_limit").get_value() + + # GtkUI + for key in new_gtkui_config.keys(): + # The values do not match so this needs to be updated + if self.gtkui_config[key] != new_gtkui_config[key]: + self.gtkui_config[key] = new_gtkui_config[key] + + # Core + if client.get_core_uri() != None: + # Only do this if we're connected to a daemon + config_to_set = {} + for key in new_core_config.keys(): + # The values do not match so this needs to be updated + if self.core_config[key] != new_core_config[key]: + config_to_set[key] = new_core_config[key] + + # Set each changed config value in the core + client.set_config(config_to_set) + client.force_call(True) + # Update the configuration + self.core_config.update(config_to_set) + + # Re-show the dialog to make sure everything has been updated + self.show() + + def hide(self): + self.pref_dialog.hide() + + def on_pref_dialog_delete_event(self, widget, event): + self.hide() + return True + + def on_toggle(self, widget): + """Handles widget sensitivity based on radio/check button values.""" + try: + value = widget.get_active() + except: + return + + dependents = { + "chk_show_dialog": {"chk_focus_dialog": True}, + "chk_random_port": {"spin_port_min": False, + "spin_port_max": False}, + "chk_use_tray": {"chk_min_on_close": True, + "chk_start_in_tray": True, + "chk_lock_tray": True}, + "chk_lock_tray": {"txt_tray_password": True, + "password_label": True}, + "radio_open_folder_custom": {"combo_file_manager": False, + "txt_open_folder_location": True}, + "chk_move_completed" : {"move_completed_path_button" : True}, + "chk_copy_torrent_file" : {"torrent_files_button" : True}, + "chk_autoadd" : {"folder_autoadd" : True}, + "chk_seed_ratio" : {"spin_share_ratio": True, + "chk_remove_ratio" : True} + } + + def update_dependent_widgets(name, value): + dependency = dependents[name] + for dep in dependency.keys(): + depwidget = self.glade.get_widget(dep) + sensitive = [not value, value][dependency[dep]] + depwidget.set_sensitive(sensitive) + if dep in dependents: + update_dependent_widgets(dep, depwidget.get_active() and sensitive) + + for key in dependents.keys(): + if widget != self.glade.get_widget(key): + continue + update_dependent_widgets(key, value) + + def on_button_ok_clicked(self, data): + log.debug("on_button_ok_clicked") + self.set_config() + component.get("PluginManager").run_on_apply_prefs() + self.hide() + return True + + def on_button_apply_clicked(self, data): + log.debug("on_button_apply_clicked") + self.set_config() + component.get("PluginManager").run_on_apply_prefs() + + def on_button_cancel_clicked(self, data): + log.debug("on_button_cancel_clicked") + self.hide() + return True + + def on_selection_changed(self, treeselection): + # Show the correct notebook page based on what row is selected. + (model, row) = treeselection.get_selected() + self.notebook.set_current_page(model.get_value(row, 0)) + + def on_test_port_clicked(self, data): + log.debug("on_test_port_clicked") + def on_get_listen_port(port): + deluge.common.open_url_in_browser( + "http://deluge-torrent.org/test-port.php?port=%s" % port) + client.get_listen_port(on_get_listen_port) + client.force_call() + + def on_plugin_toggled(self, renderer, path): + log.debug("on_plugin_toggled") + row = self.plugin_liststore.get_iter_from_string(path) + name = self.plugin_liststore.get_value(row, 0) + value = self.plugin_liststore.get_value(row, 1) + self.plugin_liststore.set_value(row, 1, not value) + if not value: + client.enable_plugin(name) + component.get("PluginManager").enable_plugin(name) + else: + client.disable_plugin(name) + component.get("PluginManager").disable_plugin(name) + + def on_plugin_selection_changed(self, treeselection): + log.debug("on_plugin_selection_changed") + diff --git a/deluge/ui/gtkui/queuedtorrents.py b/deluge/ui/gtkui/queuedtorrents.py new file mode 100644 index 000000000..7b10b330b --- /dev/null +++ b/deluge/ui/gtkui/queuedtorrents.py @@ -0,0 +1,185 @@ +# +# queuedtorrents.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 os.path + +import gtk, gtk.glade +import gobject +import pkg_resources + +import deluge.component as component +from deluge.ui.client import aclient as client +import deluge.common +from deluge.configmanager import ConfigManager +from deluge.log import LOG as log + +class QueuedTorrents(component.Component): + def __init__(self): + component.Component.__init__(self, "QueuedTorrents", depend=["StatusBar"]) + self.queue = [] + self.status_item = None + + self.config = ConfigManager("gtkui.conf") + self.glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/queuedtorrents.glade")) + self.glade.get_widget("chk_autoadd").set_active( + self.config["autoadd_queued"]) + self.dialog = self.glade.get_widget("queued_torrents_dialog") + self.dialog.set_icon(deluge.common.get_logo(32)) + + self.glade.signal_autoconnect({ + "on_button_remove_clicked": self.on_button_remove_clicked, + "on_button_clear_clicked": self.on_button_clear_clicked, + "on_button_close_clicked": self.on_button_close_clicked, + "on_button_add_clicked": self.on_button_add_clicked, + "on_chk_autoadd_toggled": self.on_chk_autoadd_toggled + }) + + self.treeview = self.glade.get_widget("treeview") + self.treeview.append_column( + gtk.TreeViewColumn(_("Torrent"), gtk.CellRendererText(), text=0)) + + self.liststore = gtk.ListStore(str, str) + self.treeview.set_model(self.liststore) + + def run(self): + self.dialog.set_transient_for(component.get("MainWindow").window) + self.dialog.show() + + def start(self): + if len(self.queue) == 0: + return + + if self.config["autoadd_queued"] or self.config["classic_mode"]: + self.on_button_add_clicked(None) + return + # Make sure status bar info is showing + self.update_status_bar() + + # We only want the add button sensitive if we're connected to a host + self.glade.get_widget("button_add").set_sensitive(True) + self.run() + + def stop(self): + # We only want the add button sensitive if we're connected to a host + self.glade.get_widget("button_add").set_sensitive(False) + self.update_status_bar() + + def add_to_queue(self, torrents): + """Adds the list of torrents to the queue""" + # Add to the queue while removing duplicates + self.queue = list(set(self.queue + torrents)) + + # Update the liststore + self.liststore.clear() + for torrent in self.queue: + self.liststore.append([os.path.split(torrent)[1], torrent]) + + # Update the status bar + self.update_status_bar() + + def update_status_bar(self): + """Attempts to update status bar""" + # If there are no queued torrents.. remove statusbar widgets and return + if len(self.queue) == 0: + if self.status_item != None: + component.get("StatusBar").remove_item(self.status_item) + self.status_item = None + return False + + try: + statusbar = component.get("StatusBar") + except Exception, e: + # The statusbar hasn't been loaded yet, so we'll add a timer to + # update it later. + gobject.timeout_add(100, self.update_status_bar) + return False + + # Set the label text for statusbar + if len(self.queue) > 1: + label = str(len(self.queue)) + _(" Torrents Queued") + else: + label = str(len(self.queue)) + _(" Torrent Queued") + + # Add the statusbar items if needed, or just modify the label if they + # have already been added. + if self.status_item == None: + self.status_item = component.get("StatusBar").add_item( + stock=gtk.STOCK_SORT_DESCENDING, + text=label, + callback=self.on_statusbar_click) + else: + self.status_item.set_text(label) + + # We return False so the timer stops + return False + + def on_statusbar_click(self, widget, event): + log.debug("on_statusbar_click") + self.run() + + def on_button_remove_clicked(self, widget): + selected = self.treeview.get_selection().get_selected()[1] + if selected != None: + path = self.liststore.get_value(selected, 1) + self.liststore.remove(selected) + self.queue.remove(path) + self.update_status_bar() + + def on_button_clear_clicked(self, widget): + self.liststore.clear() + self.update_status_bar() + + def on_button_close_clicked(self, widget): + self.dialog.hide() + + def on_button_add_clicked(self, widget): + # Add all the torrents in the liststore + def add_torrent(model, path, iter, data): + torrent_path = model.get_value(iter, 1) + if self.config["interactive_add"]: + component.get("AddTorrentDialog").add_from_files([torrent_path]) + component.get("AddTorrentDialog").show(self.config["focus_add_dialog"]) + else: + client.add_torrent_file([torrent_path]) + + self.liststore.foreach(add_torrent, None) + del self.queue[:] + self.dialog.hide() + self.update_status_bar() + + def on_chk_autoadd_toggled(self, widget): + self.config["autoadd_queued"] = widget.get_active() + + diff --git a/deluge/ui/gtkui/removetorrentdialog.py b/deluge/ui/gtkui/removetorrentdialog.py new file mode 100644 index 000000000..8f2555585 --- /dev/null +++ b/deluge/ui/gtkui/removetorrentdialog.py @@ -0,0 +1,90 @@ +# +# removetorrentdialog.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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, gtk.glade +import pkg_resources + +import deluge.common +from deluge.ui.client import aclient as client +import deluge.component as component +from deluge.log import LOG as log + +class RemoveTorrentDialog: + def __init__(self, torrent_ids, remove_torrentfile=False, remove_data=False): + self.torrent_ids = torrent_ids + self.remove_torrentfile = remove_torrentfile + self.remove_data = remove_data + + self.glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/remove_torrent_dialog.glade")) + + self.dialog = self.glade.get_widget("remove_torrent_dialog") + self.dialog.set_icon(deluge.common.get_logo(32)) + self.dialog.set_transient_for(component.get("MainWindow").window) + + self.glade.signal_autoconnect({ + "on_button_ok_clicked": self.on_button_ok_clicked, + "on_button_cancel_clicked": self.on_button_cancel_clicked + }) + + if len(self.torrent_ids) > 1: + # We need to pluralize the dialog + self.dialog.set_title("Remove Torrents?") + self.glade.get_widget("label_title").set_markup( + _("Are you sure you want to remove the selected torrents?")) + self.glade.get_widget("button_ok").set_label(_("Remove Selected Torrents")) + + if self.remove_torrentfile or self.remove_data: + self.glade.get_widget("hseparator1").show() + if self.remove_torrentfile: + self.glade.get_widget("hbox_torrentfile").show() + if self.remove_data: + self.glade.get_widget("hbox_data").show() + + def run(self): + if self.torrent_ids == None or self.torrent_ids == []: + self.dialog.destroy() + return + self.dialog.show() + + def on_button_ok_clicked(self, widget): + client.remove_torrent( + self.torrent_ids, self.remove_torrentfile, self.remove_data) + # Unselect all to avoid issues with the selection changed event + component.get("TorrentView").treeview.get_selection().unselect_all() + self.dialog.destroy() + + def on_button_cancel_clicked(self, widget): + self.dialog.destroy() + diff --git a/deluge/ui/gtkui/sidebar.py b/deluge/ui/gtkui/sidebar.py new file mode 100644 index 000000000..2cb2b7f06 --- /dev/null +++ b/deluge/ui/gtkui/sidebar.py @@ -0,0 +1,114 @@ +# +# sidebar.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 +import gtk.glade + +import deluge.component as component +import deluge.common +from deluge.log import LOG as log + +class SideBar(component.Component): + def __init__(self): + component.Component.__init__(self, "SideBar") + self.window = component.get("MainWindow") + glade = self.window.main_glade + self.label_view = glade.get_widget("label_view") + self.hpaned = glade.get_widget("hpaned") + self.scrolled = glade.get_widget("scrolledwindow_sidebar") + self.is_visible = True + + # Create the liststore + self.liststore = gtk.ListStore(str, gtk.gdk.Pixbuf) + self.liststore.append([_("All"), None]) + self.liststore.append([_("Downloading"), + gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("downloading16.png"))]) + self.liststore.append([_("Seeding"), + gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("seeding16.png"))]) + self.liststore.append([_("Queued"), + gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("queued16.png"))]) + self.liststore.append([_("Paused"), + gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("inactive16.png"))]) + self.liststore.append([_("Error"), + gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("alert16.png"))]) + self.liststore.append([_("Checking"), + gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("checking16.png"))]) + # Create the column + column = gtk.TreeViewColumn(_("Labels")) + column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + render = gtk.CellRendererPixbuf() + column.pack_start(render, expand=False) + column.add_attribute(render, 'pixbuf', 1) + render = gtk.CellRendererText() + column.pack_start(render, expand=True) + column.add_attribute(render, 'text', 0) + self.label_view.append_column(column) + + self.label_view.set_model(self.liststore) + + self.label_view.get_selection().connect("changed", + self.on_selection_changed) + + # Select the 'All' label on init + self.label_view.get_selection().select_iter( + self.liststore.get_iter_first()) + + def visible(self, visible): + if visible: + self.scrolled.show() + else: + self.scrolled.hide() + self.hpaned.set_position(-1) + + self.is_visible = visible + + def on_selection_changed(self, selection): + try: + (model, row) = self.label_view.get_selection().get_selected() + except Exception, e: + log.debug(e) + # paths is likely None .. so lets return None + return None + + value = model.get_value(row, 0) + if value == "All": + component.get("TorrentView").set_filter(None, None) + else: + component.get("TorrentView").set_filter("state", value) + diff --git a/deluge/ui/gtkui/signals.py b/deluge/ui/gtkui/signals.py new file mode 100644 index 000000000..0f3e594dd --- /dev/null +++ b/deluge/ui/gtkui/signals.py @@ -0,0 +1,156 @@ +# +# signals.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 + +import deluge.component as component +from deluge.ui.client import aclient as client +from deluge.ui.signalreceiver import SignalReceiver +from deluge.configmanager import ConfigManager +from deluge.log import LOG as log + +class Signals(component.Component): + def __init__(self): + component.Component.__init__(self, "Signals") + self.receiver = SignalReceiver() + self.config = ConfigManager("gtkui.conf") + + def start(self): + if not client.is_localhost(): + self.receiver.set_remote(True) + + self.receiver.run() + self.config["signal_port"] = self.receiver.get_port() + self.receiver.connect_to_signal("torrent_added", + self.torrent_added_signal) + self.receiver.connect_to_signal("torrent_removed", + self.torrent_removed_signal) + self.receiver.connect_to_signal("torrent_paused", self.torrent_paused) + self.receiver.connect_to_signal("torrent_resumed", + self.torrent_resumed) + self.receiver.connect_to_signal("torrent_all_paused", + self.torrent_all_paused) + self.receiver.connect_to_signal("torrent_all_resumed", + self.torrent_all_resumed) + self.receiver.connect_to_signal("config_value_changed", + self.config_value_changed) + self.receiver.connect_to_signal("torrent_queue_changed", + self.torrent_queue_changed) + self.receiver.connect_to_signal("torrent_resume_at_stop_ratio", + self.torrent_resume_at_stop_ratio) + self.receiver.connect_to_signal("new_version_available", + self.new_version_available) + self.receiver.connect_to_signal("args_from_external", + self.args_from_external) + self.receiver.connect_to_signal("torrent_state_changed", + self.torrent_state_changed) + + def stop(self): + try: + self.receiver.shutdown() + except: + pass + + def connect_to_signal(self, signal, callback): + """Connects a callback to a signal""" + self.receiver.connect_to_signal(signal, callback) + + def torrent_added_signal(self, torrent_id): + log.debug("torrent_added signal received..") + log.debug("torrent id: %s", torrent_id) + # Add the torrent to the treeview + component.get("TorrentView").add_row(torrent_id) + + def torrent_removed_signal(self, torrent_id): + log.debug("torrent_remove signal received..") + log.debug("torrent id: %s", torrent_id) + # Remove the torrent from the treeview + component.get("TorrentView").remove_row(torrent_id) + + def torrent_paused(self, torrent_id): + log.debug("torrent_paused signal received..") + component.get("TorrentView").mark_dirty(torrent_id) + component.get("TorrentView").update() + component.get("ToolBar").update_buttons() + component.get("MenuBar").update_menu() + + def torrent_resumed(self, torrent_id): + log.debug("torrent_resumed signal received..") + component.get("TorrentView").mark_dirty(torrent_id) + component.get("TorrentView").update() + component.get("ToolBar").update_buttons() + component.get("MenuBar").update_menu() + + def torrent_all_paused(self): + log.debug("torrent_all_paused signal received..") + component.get("TorrentView").mark_dirty() + component.get("TorrentView").update() + component.get("ToolBar").update_buttons() + component.get("MenuBar").update_menu() + + def torrent_all_resumed(self): + log.debug("torrent_all_resumed signal received..") + component.get("TorrentView").mark_dirty() + component.get("TorrentView").update() + component.get("ToolBar").update_buttons() + component.get("MenuBar").update_menu() + + def config_value_changed(self, key, value): + log.debug("config_value_changed signal received..") + component.get("StatusBar").config_value_changed(key, value) + component.get("SystemTray").config_value_changed(key, value) + + def torrent_queue_changed(self): + log.debug("torrent_queue_changed signal received..") + component.get("TorrentView").mark_dirty() + component.get("TorrentView").update() + + def torrent_resume_at_stop_ratio(self): + log.debug("torrent_resume_at_stop_ratio") + component.get("StatusBar").display_warning( + text=_("Torrent is past stop ratio.")) + + def new_version_available(self, value): + log.debug("new_version_available: %s", value) + if self.config["show_new_releases"]: + from deluge.ui.gtkui.new_release_dialog import NewReleaseDialog + NewReleaseDialog().show(value) + + def args_from_external(self, value): + log.debug("args_from_external: %s", value) + import ipcinterface + ipcinterface.process_args(value) + + def torrent_state_changed(self, value): + log.debug("torrent_state_changed: %s", value) + diff --git a/deluge/ui/gtkui/statistics_tab.py b/deluge/ui/gtkui/statistics_tab.py new file mode 100644 index 000000000..43f20dc47 --- /dev/null +++ b/deluge/ui/gtkui/statistics_tab.py @@ -0,0 +1,147 @@ +# +# statistics_tab.py +# +# Copyright (C) 2008 Andrew Resch ('andar') +# +# 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 2 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, gtk.glade + +from deluge.ui.client import aclient as client +import deluge.component as component +import deluge.common +from deluge.ui.gtkui.torrentdetails import Tab +from deluge.log import LOG as log + +def fpeer_sized(first, second): + return "%s (%s)" % (deluge.common.fsize(first), deluge.common.fsize(second)) + +def fpeer_size_second(first, second): + return "%s (%s)" % (first, deluge.common.fsize(second)) + +def fratio(value): + return "%.3f" % value + +def fpcnt(value): + return "%.2f%%" % value + +def fspeed(value, max_value=-1): + if max_value > -1: + return "%s [%s KiB/s]" % (deluge.common.fspeed(value), max_value) + else: + return deluge.common.fspeed(value) + +class StatisticsTab(Tab): + def __init__(self): + # Get the labels we need to update. + # widgetname, modifier function, status keys + glade = component.get("MainWindow").main_glade + + self._name = "Statistics" + self._child_widget = glade.get_widget("statistics_tab") + self._tab_label = glade.get_widget("statistics_tab_label") + + self.label_widgets = [ + (glade.get_widget("summary_pieces"), fpeer_size_second, ("num_pieces", "piece_length")), + (glade.get_widget("summary_availability"), fratio, ("distributed_copies",)), + (glade.get_widget("summary_total_downloaded"), fpeer_sized, ("total_done", "total_payload_download")), + (glade.get_widget("summary_total_uploaded"), fpeer_sized, ("total_uploaded", "total_payload_upload")), + (glade.get_widget("summary_download_speed"), fspeed, ("download_payload_rate", "max_download_speed")), + (glade.get_widget("summary_upload_speed"), fspeed, ("upload_payload_rate", "max_upload_speed")), + (glade.get_widget("summary_seeders"), deluge.common.fpeer, ("num_seeds", "total_seeds")), + (glade.get_widget("summary_peers"), deluge.common.fpeer, ("num_peers", "total_peers")), + (glade.get_widget("summary_eta"), deluge.common.ftime, ("eta",)), + (glade.get_widget("summary_share_ratio"), fratio, ("ratio",)), + (glade.get_widget("summary_tracker_status"), None, ("tracker_status",)), + (glade.get_widget("summary_next_announce"), deluge.common.ftime, ("next_announce",)), + (glade.get_widget("summary_active_time"), deluge.common.ftime, ("active_time",)), + (glade.get_widget("summary_seed_time"), deluge.common.ftime, ("seeding_time",)), + (glade.get_widget("summary_seed_rank"), str, ("seed_rank",)), + (glade.get_widget("summary_auto_managed"), str, ("is_auto_managed",)), + (glade.get_widget("progressbar"), fpcnt, ("progress",)) + ] + + def update(self): + # Get the first selected torrent + selected = component.get("TorrentView").get_selected_torrents() + + # Only use the first torrent in the list or return if None selected + if len(selected) != 0: + selected = selected[0] + else: + # No torrent is selected in the torrentview + return + + # Get the torrent status + status_keys = ["progress", "num_pieces", "piece_length", + "distributed_copies", "total_done", "total_payload_download", + "total_uploaded", "total_payload_upload", "download_payload_rate", + "upload_payload_rate", "num_peers", "num_seeds", "total_peers", + "total_seeds", "eta", "ratio", "next_announce", + "tracker_status", "max_connections", "max_upload_slots", + "max_upload_speed", "max_download_speed", "active_time", + "seeding_time", "seed_rank", "is_auto_managed"] + + client.get_torrent_status( + self._on_get_torrent_status, selected, status_keys) + + def _on_get_torrent_status(self, status): + # Check to see if we got valid data from the core + if status is None: + return + + # Update all the label widgets + for widget in self.label_widgets: + if widget[1] != None: + args = [] + try: + for key in widget[2]: + args.append(status[key]) + except Exception, e: + log.debug("Unable to get status value: %s", e) + continue + + txt = widget[1](*args) + else: + txt = status[widget[2][0]] + + if widget[0].get_text() != txt: + widget[0].set_text(txt) + + # Do the progress bar because it's a special case (not a label) + w = component.get("MainWindow").main_glade.get_widget("progressbar") + fraction = status["progress"] / 100 + if w.get_fraction() != fraction: + w.set_fraction(fraction) + + def clear(self): + for widget in self.label_widgets: + widget[0].set_text("") + + component.get("MainWindow").main_glade.get_widget("progressbar").set_fraction(0.0) diff --git a/deluge/ui/gtkui/statusbar.py b/deluge/ui/gtkui/statusbar.py new file mode 100644 index 000000000..31443ee6e --- /dev/null +++ b/deluge/ui/gtkui/statusbar.py @@ -0,0 +1,431 @@ +# +# statusbar.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 +import gobject + +import deluge.component as component +import deluge.common +from deluge.configmanager import ConfigManager +from deluge.ui.client import aclient as client +from deluge.log import LOG as log + +class StatusBarItem: + def __init__(self, image=None, stock=None, text=None, callback=None): + self._widgets = [] + self._ebox = gtk.EventBox() + self._hbox = gtk.HBox() + self._hbox.set_spacing(5) + self._image = gtk.Image() + self._label = gtk.Label() + self._hbox.add(self._image) + self._hbox.add(self._label) + self._ebox.add(self._hbox) + + # Add image from file or stock + if image != None or stock != None: + if image != None: + self.set_image_from_file(image) + if stock != None: + self.set_image_from_stock(stock) + + # Add text + if text != None: + self.set_text(text) + + if callback != None: + self.set_callback(callback) + + self.show_all() + + def set_callback(self, callback): + self._ebox.connect("button-press-event", callback) + + def show_all(self): + self._ebox.show() + self._hbox.show() + self._image.show() + self._label.show() + + def set_image_from_file(self, image): + self._image.set_from_file(image) + + def set_image_from_stock(self, stock): + self._image.set_from_stock(stock, gtk.ICON_SIZE_MENU) + + def set_text(self, text): + if self._label.get_text() != text: + self._label.set_text(text) + + def get_widgets(self): + return self._widgets() + + def get_eventbox(self): + return self._ebox + + def get_text(self): + return self._label.get_text() + +class StatusBar(component.Component): + def __init__(self): + component.Component.__init__(self, "StatusBar", interval=3000) + self.window = component.get("MainWindow") + self.statusbar = self.window.main_glade.get_widget("statusbar") + self.tooltips = gtk.Tooltips() + self.config = ConfigManager("gtkui.conf") + + # Status variables that are updated via callback + self.max_connections = -1 + self.num_connections = 0 + self.max_download_speed = -1.0 + self.download_rate = 0.0 + self.max_upload_speed = -1.0 + self.upload_rate = 0.0 + self.dht_nodes = 0 + self.dht_status = False + self.health = False + + self.config_value_changed_dict = { + "max_connections_global": self._on_max_connections_global, + "max_download_speed": self._on_max_download_speed, + "max_upload_speed": self._on_max_upload_speed, + "dht": self._on_dht + } + self.current_warnings = [] + # Add a HBox to the statusbar after removing the initial label widget + self.hbox = gtk.HBox() + self.hbox.set_spacing(10) + frame = self.statusbar.get_children()[0] + frame.remove(frame.get_children()[0]) + frame.add(self.hbox) + self.statusbar.show_all() + # Create the not connected item + self.not_connected_item = StatusBarItem( + stock=gtk.STOCK_STOP, text=_("Not Connected"), + callback=self._on_notconnected_item_clicked) + # Show the not connected status bar + self.show_not_connected() + + def start(self): + # Add in images and labels + self.remove_item(self.not_connected_item) + + self.connections_item = self.add_item( + stock=gtk.STOCK_NETWORK, + callback=self._on_connection_item_clicked, + tooltip=_("Connections")) + + self.download_item = self.add_item( + image=deluge.common.get_pixmap("downloading16.png"), + callback=self._on_download_item_clicked, + tooltip=_("Download Speed")) + + self.upload_item = self.add_item( + image=deluge.common.get_pixmap("seeding16.png"), + callback=self._on_upload_item_clicked, + tooltip=_("Upload Speed")) + + self.dht_item = StatusBarItem( + image=deluge.common.get_pixmap("dht16.png")) + self.tooltips.set_tip(self.dht_item.get_eventbox(), "DHT Nodes") + + self.health_item = self.add_item( + stock=gtk.STOCK_DIALOG_ERROR, + text=_("No Incoming Connections!"), + callback=self._on_health_icon_clicked) + + self.health = False + + # Get some config values + client.get_config_value( + self._on_max_connections_global, "max_connections_global") + client.get_config_value( + self._on_max_download_speed, "max_download_speed") + client.get_config_value( + self._on_max_upload_speed, "max_upload_speed") + client.get_config_value( + self._on_dht, "dht") + client.get_health(self._on_get_health) + + self.send_status_request() + + def stop(self): + # When stopped, we just show the not connected thingy + try: + self.remove_item(self.connections_item) + self.remove_item(self.dht_item) + self.remove_item(self.download_item) + self.remove_item(self.upload_item) + self.remove_item(self.not_connected_item) + self.remove_item(self.health_item) + except Exception, e: + log.debug("Unable to remove StatusBar item: %s", e) + self.show_not_connected() + + def visible(self, visible): + if visible: + self.statusbar.show() + else: + self.statusbar.hide() + + def show_not_connected(self): + self.hbox.pack_start( + self.not_connected_item.get_eventbox(), expand=False, fill=False) + + def add_item(self, image=None, stock=None, text=None, callback=None, tooltip=None): + """Adds an item to the status bar""" + # The return tuple.. we return whatever widgets we add + item = StatusBarItem(image, stock, text, callback) + self.hbox.pack_start(item.get_eventbox(), expand=False, fill=False) + if tooltip: + self.tooltips.set_tip(item.get_eventbox(), tooltip) + return item + + def remove_item(self, item): + """Removes an item from the statusbar""" + if item.get_eventbox() in self.hbox.get_children(): + try: + self.hbox.remove(item.get_eventbox()) + except Exception, e: + log.debug("Unable to remove widget: %s", e) + + def add_timeout_item(self, seconds=3, image=None, stock=None, text=None, callback=None): + """Adds an item to the StatusBar for seconds""" + item = self.add_item(image, stock, text, callback) + # Start a timer to remove this item in seconds + gobject.timeout_add(seconds * 1000, self.remove_item, item) + + def display_warning(self, text, callback=None): + """Displays a warning to the user in the status bar""" + if text not in self.current_warnings: + item = self.add_item( + stock=gtk.STOCK_DIALOG_WARNING, text=text, callback=callback) + self.current_warnings.append(text) + gobject.timeout_add(3000, self.remove_warning, item) + + def remove_warning(self, item): + self.current_warnings.remove(item.get_text()) + self.remove_item(item) + + def clear_statusbar(self): + def remove(child): + self.hbox.remove(child) + self.hbox.foreach(remove) + + def send_status_request(self): + # Sends an async request for data from the core + client.get_num_connections(self._on_get_num_connections) + if self.dht_status: + client.get_dht_nodes(self._on_get_dht_nodes) + client.get_download_rate(self._on_get_download_rate) + client.get_upload_rate(self._on_get_upload_rate) + if not self.health: + # Only request health status while False + client.get_health(self._on_get_health) + + def config_value_changed(self, key, value): + """This is called when we received a config_value_changed signal from + the core.""" + + if key in self.config_value_changed_dict.keys(): + self.config_value_changed_dict[key](value) + + def _on_max_connections_global(self, max_connections): + self.max_connections = max_connections + self.update_connections_label() + + def _on_get_num_connections(self, num_connections): + self.num_connections = num_connections + self.update_connections_label() + + def _on_get_dht_nodes(self, dht_nodes): + self.dht_nodes = dht_nodes + self.update_dht_label() + + def _on_dht(self, value): + self.dht_status = value + if value: + self.hbox.pack_start( + self.dht_item.get_eventbox(), expand=False, fill=False) + client.get_dht_nodes(self._on_get_dht_nodes) + else: + self.remove_item(self.dht_item) + + def _on_max_download_speed(self, max_download_speed): + self.max_download_speed = max_download_speed + self.update_download_label() + + def _on_get_download_rate(self, download_rate): + self.download_rate = deluge.common.fsize(download_rate) + self.update_download_label() + + def _on_max_upload_speed(self, max_upload_speed): + self.max_upload_speed = max_upload_speed + self.update_upload_label() + + def _on_get_upload_rate(self, upload_rate): + self.upload_rate = deluge.common.fsize(upload_rate) + self.update_upload_label() + + def _on_get_health(self, value): + self.health = value + if self.health: + self.remove_item(self.health_item) + + def update_connections_label(self): + # Set the max connections label + if self.max_connections < 0: + label_string = "%s" % self.num_connections + else: + label_string = "%s (%s)" % (self.num_connections, self.max_connections) + + self.connections_item.set_text(label_string) + + def update_dht_label(self): + # Set the max connections label + self.dht_item.set_text("%s" % (self.dht_nodes)) + + def update_download_label(self): + # Set the download speed label + if self.max_download_speed < 0: + label_string = "%s/s" % self.download_rate + else: + label_string = "%s/s (%s %s)" % ( + self.download_rate, self.max_download_speed, _("KiB/s")) + + self.download_item.set_text(label_string) + + def update_upload_label(self): + # Set the upload speed label + if self.max_upload_speed < 0: + label_string = "%s/s" % self.upload_rate + else: + label_string = "%s/s (%s %s)" % ( + self.upload_rate, self.max_upload_speed, _("KiB/s")) + + self.upload_item.set_text(label_string) + + def update(self): + # Send status request + self.send_status_request() + + def _on_download_item_clicked(self, widget, event): + menu = deluge.common.build_menu_radio_list( + self.config["tray_download_speed_list"], + self._on_set_download_speed, + self.max_download_speed, + _("KiB/s"), show_notset=True, show_other=True) + menu.show_all() + menu.popup(None, None, None, event.button, event.time) + + def _on_set_download_speed(self, widget): + log.debug("_on_set_download_speed") + value = widget.get_children()[0].get_text().split(" ")[0] + log.debug("value: %s", value) + if value == "Unlimited": + value = -1 + + if value == _("Other..."): + value = deluge.common.show_other_dialog( + _("Download Speed (KiB/s):"), self.max_download_speed) + if value == None: + return + + # Set the config in the core + value = float(value) + + if value != self.max_download_speed: + client.set_config({"max_download_speed": value}) + + def _on_upload_item_clicked(self, widget, event): + menu = deluge.common.build_menu_radio_list( + self.config["tray_upload_speed_list"], + self._on_set_upload_speed, + self.max_upload_speed, + _("KiB/s"), show_notset=True, show_other=True) + menu.show_all() + menu.popup(None, None, None, event.button, event.time) + + def _on_set_upload_speed(self, widget): + log.debug("_on_set_upload_speed") + value = widget.get_children()[0].get_text().split(" ")[0] + log.debug("value: %s", value) + + if value == "Unlimited": + value = -1 + + if value == _("Other..."): + value = deluge.common.show_other_dialog( + _("Upload Speed (KiB/s):"), self.max_upload_speed) + if value == None: + return + + # Set the config in the core + value = float(value) + + if value != self.max_upload_speed: + client.set_config({"max_upload_speed": value}) + + def _on_connection_item_clicked(self, widget, event): + menu = deluge.common.build_menu_radio_list( + self.config["connection_limit_list"], + self._on_set_connection_limit, + self.max_connections, show_notset=True, show_other=True) + menu.show_all() + menu.popup(None, None, None, event.button, event.time) + + def _on_set_connection_limit(self, widget): + log.debug("_on_set_connection_limit") + value = widget.get_children()[0].get_text().split(" ")[0] + log.debug("value: %s", value) + + if value == "Unlimited": + value = -1 + + if value == _("Other..."): + value = deluge.common.show_other_dialog( + _("Connection Limit:"), self.max_connections) + if value == None: + return + + # Set the config in the core + value = int(value) + + if value != self.max_connections: + client.set_config({"max_connections_global": value}) + + def _on_health_icon_clicked(self, widget, event): + component.get("Preferences").show("Network") + + def _on_notconnected_item_clicked(self, widget, event): + component.get("ConnectionManager").show() diff --git a/deluge/ui/gtkui/systemtray.py b/deluge/ui/gtkui/systemtray.py new file mode 100644 index 000000000..c9b717c50 --- /dev/null +++ b/deluge/ui/gtkui/systemtray.py @@ -0,0 +1,367 @@ +# +# systemtray.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 +import pkg_resources + +import deluge.component as component +from deluge.ui.client import aclient as client +import deluge.common +from deluge.configmanager import ConfigManager +from deluge.log import LOG as log + +class SystemTray(component.Component): + def __init__(self): + component.Component.__init__(self, "SystemTray", interval=4000) + self.window = component.get("MainWindow") + self.config = ConfigManager("gtkui.conf") + # List of widgets that need to be hidden when not connected to a host + self.hide_widget_list = [ + "menuitem_add_torrent", + "menuitem_pause_all", + "menuitem_resume_all", + "menuitem_download_limit", + "menuitem_upload_limit", + "menuitem_quitdaemon", + "separatormenuitem1", + "separatormenuitem2", + "separatormenuitem3", + "separatormenuitem4" + ] + self.config.register_set_function("enable_system_tray", + self.on_enable_system_tray_set) + + self.max_download_speed = -1.0 + self.download_rate = 0.0 + self.max_upload_speed = -1.0 + self.upload_rate = 0.0 + + self.config_value_changed_dict = { + "max_download_speed": self._on_max_download_speed, + "max_upload_speed": self._on_max_upload_speed + } + + def enable(self): + """Enables the system tray icon.""" + log.debug("Enabling the system tray icon..") + self.tray_glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/tray_menu.glade")) + + try: + self.tray = gtk.status_icon_new_from_icon_name("deluge") + except: + log.warning("Update PyGTK to 2.10 or greater for SystemTray..") + return + + self.tray.connect("activate", self.on_tray_clicked) + self.tray.connect("popup-menu", self.on_tray_popup) + + + self.tray_glade.signal_autoconnect({ + "on_menuitem_show_deluge_activate": \ + self.on_menuitem_show_deluge_activate, + "on_menuitem_add_torrent_activate": \ + self.on_menuitem_add_torrent_activate, + "on_menuitem_pause_all_activate": \ + self.on_menuitem_pause_all_activate, + "on_menuitem_resume_all_activate": \ + self.on_menuitem_resume_all_activate, + "on_menuitem_quit_activate": self.on_menuitem_quit_activate, + "on_menuitem_quitdaemon_activate": \ + self.on_menuitem_quitdaemon_activate + }) + + self.tray_menu = self.tray_glade.get_widget("tray_menu") + + self.tray_glade.get_widget("download-limit-image").set_from_file( + deluge.common.get_pixmap("downloading16.png")) + self.tray_glade.get_widget("upload-limit-image").set_from_file( + deluge.common.get_pixmap("seeding16.png")) + + if self.config["classic_mode"]: + self.hide_widget_list.remove("menuitem_quitdaemon") + self.hide_widget_list.remove("separatormenuitem4") + self.tray_glade.get_widget("menuitem_quitdaemon").hide() + self.tray_glade.get_widget("separatormenuitem4").hide() + + if client.get_core_uri() == None: + # Hide menu widgets because we're not connected to a host. + for widget in self.hide_widget_list: + self.tray_glade.get_widget(widget).hide() + + def start(self): + if self.config["enable_system_tray"]: + # Show widgets in the hide list because we've connected to a host + for widget in self.hide_widget_list: + self.tray_glade.get_widget(widget).show() + + # Build the bandwidth speed limit menus + self.build_tray_bwsetsubmenu() + + # Get some config values + client.get_config_value( + self._on_max_download_speed, "max_download_speed") + client.get_config_value( + self._on_max_upload_speed, "max_upload_speed") + self.send_status_request() + + def stop(self): + try: + # Hide widgets in hide list because we're not connected to a host + for widget in self.hide_widget_list: + self.tray_glade.get_widget(widget).hide() + except Exception, e: + log.debug("Unable to hide system tray menu widgets: %s", e) + self.tray.set_visible(False) + + def send_status_request(self): + client.get_download_rate(self._on_get_download_rate) + client.get_upload_rate(self._on_get_upload_rate) + + def config_value_changed(self, key, value): + """This is called when we received a config_value_changed signal from + the core.""" + + if key in self.config_value_changed_dict.keys(): + self.config_value_changed_dict[key](value) + + def _on_max_download_speed(self, max_download_speed): + if self.max_download_speed != max_download_speed: + self.max_download_speed = max_download_speed + self.build_tray_bwsetsubmenu() + + def _on_get_download_rate(self, download_rate): + self.download_rate = deluge.common.fsize(download_rate) + + def _on_max_upload_speed(self, max_upload_speed): + if self.max_upload_speed != max_upload_speed: + self.max_upload_speed = max_upload_speed + self.build_tray_bwsetsubmenu() + + def _on_get_upload_rate(self, upload_rate): + self.upload_rate = deluge.common.fsize(upload_rate) + + def update(self): + # Set the tool tip text + max_download_speed = self.max_download_speed + max_upload_speed = self.max_upload_speed + + if max_download_speed == -1: + max_download_speed = _("Unlimited") + else: + max_download_speed = "%s KiB/s" % (max_download_speed) + if max_upload_speed == -1: + max_upload_speed = _("Unlimited") + else: + max_upload_speed = "%s KiB/s" % (max_upload_speed) + + msg = '%s\n%s: %s (%s)\n%s: %s (%s)' % ( + _("Deluge Bittorrent Client"), _("Down Speed"), + self.download_rate, + max_download_speed, _("Up Speed"), + self.upload_rate, max_upload_speed) + + # Set the tooltip + self.tray.set_tooltip(msg) + + self.send_status_request() + + def build_tray_bwsetsubmenu(self): + # Create the Download speed list sub-menu + submenu_bwdownset = deluge.common.build_menu_radio_list( + self.config["tray_download_speed_list"], self.tray_setbwdown, + self.max_download_speed, + _("KiB/s"), show_notset=True, show_other=True) + + # Create the Upload speed list sub-menu + submenu_bwupset = deluge.common.build_menu_radio_list( + self.config["tray_upload_speed_list"], self.tray_setbwup, + self.max_upload_speed, + _("KiB/s"), show_notset=True, show_other=True) + + # Add the sub-menus to the tray menu + self.tray_glade.get_widget("menuitem_download_limit").set_submenu( + submenu_bwdownset) + self.tray_glade.get_widget("menuitem_upload_limit").set_submenu( + submenu_bwupset) + + # Show the sub-menus for all to see + submenu_bwdownset.show_all() + submenu_bwupset.show_all() + + def disable(self): + """Disables the system tray icon.""" + log.debug("Disabling the system tray icon..") + try: + self.tray.set_visible(False) + del self.tray + del self.tray_glade + del self.tray_menu + except Exception, e: + log.debug("Unable to disable system tray: %s", e) + + def on_enable_system_tray_set(self, key, value): + """Called whenever the 'enable_system_tray' config key is modified""" + if value: + self.enable() + else: + self.disable() + + def on_tray_clicked(self, icon): + """Called when the tray icon is left clicked.""" + if self.config["lock_tray"]: + if not self.unlock_tray(): + return + + if self.window.active(): + self.window.hide() + else: + self.window.present() + + def on_tray_popup(self, status_icon, button, activate_time): + """Called when the tray icon is right clicked.""" + if self.window.visible(): + self.tray_glade.get_widget("menuitem_show_deluge").set_active(True) + else: + self.tray_glade.get_widget("menuitem_show_deluge").set_active(False) + + self.tray_menu.popup(None, None, gtk.status_icon_position_menu, + button, activate_time, status_icon) + + def on_menuitem_show_deluge_activate(self, menuitem): + log.debug("on_menuitem_show_deluge_activate") + if menuitem.get_active() and not self.window.visible(): + if self.config["lock_tray"]: + if not self.unlock_tray(): + return + self.window.present() + elif not menuitem.get_active() and self.window.visible(): + self.window.hide() + + def on_menuitem_add_torrent_activate(self, menuitem): + log.debug("on_menuitem_add_torrent_activate") + from addtorrentdialog import AddTorrentDialog + client.add_torrent_file(AddTorrentDialog().show()) + + def on_menuitem_pause_all_activate(self, menuitem): + log.debug("on_menuitem_pause_all_activate") + client.pause_all_torrents() + + def on_menuitem_resume_all_activate(self, menuitem): + log.debug("on_menuitem_resume_all_activate") + client.resume_all_torrents() + + def on_menuitem_quit_activate(self, menuitem): + log.debug("on_menuitem_quit_activate") + if self.config["lock_tray"]: + if not self.unlock_tray(): + return + + if self.config["classic_mode"]: + client.shutdown() + + self.window.quit() + + def on_menuitem_quitdaemon_activate(self, menuitem): + log.debug("on_menuitem_quitdaemon_activate") + if self.config["lock_tray"]: + if not self.unlock_tray(): + return + + client.shutdown() + self.window.quit() + + def tray_setbwdown(self, widget, data=None): + self.setbwlimit(widget, _("Download"), "max_download_speed", + "tray_download_speed_list", self.max_download_speed) + + def tray_setbwup(self, widget, data=None): + self.setbwlimit(widget, _("Upload"), "max_upload_speed", + "tray_upload_speed_list", self.max_upload_speed) + + def setbwlimit(self, widget, string, core_key, ui_key, default): + """Sets the bandwidth limit based on the user selection.""" + value = widget.get_children()[0].get_text().rstrip(" " + _("KiB/s")) + if value == _("Unlimited"): + value = -1 + + if value == _("Other..."): + value = deluge.common.show_other_dialog( + string + " Speed (KiB/s):", default) + if value == None: + return + + # Set the config in the core + value = float(value) + config_to_set = {core_key: value} + client.set_config(config_to_set) + + self.build_tray_bwsetsubmenu() + + def unlock_tray(self, comingnext, is_showing_dlg=[False]): + import sha + log.debug("Show tray lock dialog") + result = False + + if is_showing_dlg[0]: + return + is_showing_dlg[0] = True + + entered_pass = gtk.Entry(25) + entered_pass.set_activates_default(True) + entered_pass.set_width_chars(25) + entered_pass.set_visibility(False) + entered_pass.show() + tray_lock = gtk.Dialog(title=_("Deluge is locked"), parent=None, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, + gtk.RESPONSE_ACCEPT)) + label = gtk.Label(_("Deluge is password protected.\nTo show the Deluge \ +window, please enter your password")) + label.set_line_wrap(True) + label.set_justify(gtk.JUSTIFY_CENTER) + tray_lock.set_position(gtk.WIN_POS_CENTER_ALWAYS) + tray_lock.set_size_request(400, 200) + tray_lock.set_default_response(gtk.RESPONSE_ACCEPT) + tray_lock.vbox.pack_start(label) + tray_lock.vbox.pack_start(entered_pass) + tray_lock.show_all() + if tray_lock.run() == gtk.RESPONSE_ACCEPT: + if self.config["tray_password"] == sha.new(entered_pass.get_text())\ + .hexdigest(): + result = True + tray_lock.destroy() + is_showing_dlg[0] = False + + return result + diff --git a/deluge/ui/gtkui/toolbar.py b/deluge/ui/gtkui/toolbar.py new file mode 100644 index 000000000..88fea9b8c --- /dev/null +++ b/deluge/ui/gtkui/toolbar.py @@ -0,0 +1,230 @@ +# +# toolbar.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 pygtk +pygtk.require('2.0') +import gtk, gtk.glade +import gobject + +import deluge.component as component +from deluge.log import LOG as log +from deluge.common import TORRENT_STATE +from deluge.ui.client import aclient as client +from deluge.configmanager import ConfigManager + +class ToolBar(component.Component): + def __init__(self): + component.Component.__init__(self, "ToolBar") + log.debug("ToolBar Init..") + self.window = component.get("MainWindow") + self.toolbar = self.window.main_glade.get_widget("toolbar") + self.config = ConfigManager("gtkui.conf") + ### Connect Signals ### + self.window.main_glade.signal_autoconnect({ + "on_toolbutton_add_clicked": self.on_toolbutton_add_clicked, + "on_toolbutton_remove_clicked": self.on_toolbutton_remove_clicked, + "on_toolbutton_pause_clicked": self.on_toolbutton_pause_clicked, + "on_toolbutton_resume_clicked": self.on_toolbutton_resume_clicked, + "on_toolbutton_preferences_clicked": \ + self.on_toolbutton_preferences_clicked, + "on_toolbutton_connectionmanager_clicked": \ + self.on_toolbutton_connectionmanager_clicked, + "on_toolbutton_queue_up_clicked": self.on_toolbutton_queue_up_clicked, + "on_toolbutton_queue_down_clicked": self.on_toolbutton_queue_down_clicked + }) + self.change_sensitivity = [ + "toolbutton_add", + "toolbutton_remove", + "toolbutton_pause", + "toolbutton_resume", + "toolbutton_queue_up", + "toolbutton_queue_down" + ] + + # Set the Remove Torrent toolbuttons drop-down menu + tb_remove = self.window.main_glade.get_widget("toolbutton_remove") + tb_remove.set_menu( + component.get("MenuBar").torrentmenu_glade.get_widget("remove_torrent_menu")) + + if self.config["classic_mode"]: + self.window.main_glade.get_widget("toolbutton_connectionmanager").hide() + + def start(self): + for widget in self.change_sensitivity: + self.window.main_glade.get_widget(widget).set_sensitive(True) + self.update_buttons() + + def stop(self): + for widget in self.change_sensitivity: + self.window.main_glade.get_widget(widget).set_sensitive(False) + + def visible(self, visible): + if visible: + self.toolbar.show() + else: + self.toolbar.hide() + + def add_toolbutton(self, callback, label=None, image=None, stock=None, + tooltip=None): + """Adds a toolbutton to the toolbar""" + # Create the button + toolbutton = gtk.ToolButton() + if stock is not None: + toolbutton.set_stock_id(stock) + if label is not None: + toolbutton.set_label(label) + if image is not None: + toolbutton.set_icon_widget(image) + # Set the tooltip + if tooltip is not None: + toolbutton.set_tooltip_text(tooltip) + # Connect the 'clicked' event callback + toolbutton.connect("clicked", callback) + + # Append the button to the toolbar + self.toolbar.insert(toolbutton, -1) + + # Show the new toolbutton + toolbutton.show_all() + + return toolbutton + + def add_separator(self, position=None): + """Adds a separator toolitem""" + sep = gtk.SeparatorToolItem() + if position is not None: + self.toolbar.insert(sep, position) + else: + # Append the separator + self.toolbar.insert(sep, -1) + + sep.show() + + return sep + + def remove(self, widget): + """Removes a widget from the toolbar""" + self.toolbar.remove(widget) + + ### Callbacks ### + def on_toolbutton_add_clicked(self, data): + log.debug("on_toolbutton_add_clicked") + # Use the menubar's callback + component.get("MenuBar").on_menuitem_addtorrent_activate(data) + + def on_toolbutton_remove_clicked(self, data): + log.debug("on_toolbutton_remove_clicked") + # Use the menubar's callbacks + component.get("MenuBar").on_menuitem_remove_session_activate(data) + + def on_toolbutton_pause_clicked(self, data): + log.debug("on_toolbutton_pause_clicked") + # Use the menubar's callbacks + component.get("MenuBar").on_menuitem_pause_activate(data) + + def on_toolbutton_resume_clicked(self, data): + log.debug("on_toolbutton_resume_clicked") + # Use the menubar's calbacks + component.get("MenuBar").on_menuitem_resume_activate(data) + + def on_toolbutton_preferences_clicked(self, data): + log.debug("on_toolbutton_preferences_clicked") + # Use the menubar's callbacks + component.get("MenuBar").on_menuitem_preferences_activate(data) + + def on_toolbutton_connectionmanager_clicked(self, data): + log.debug("on_toolbutton_connectionmanager_clicked") + # Use the menubar's callbacks + component.get("MenuBar").on_menuitem_connectionmanager_activate(data) + + def on_toolbutton_queue_up_clicked(self, data): + log.debug("on_toolbutton_queue_up_clicked") + component.get("MenuBar").on_menuitem_queue_up_activate(data) + + def on_toolbutton_queue_down_clicked(self, data): + log.debug("on_toolbutton_queue_down_clicked") + component.get("MenuBar").on_menuitem_queue_down_activate(data) + + def update_buttons(self, action=None, torrent_id=None): + if action == None: + # If all the selected torrents are paused, then disable the 'Pause' + # button. + # The same goes for the 'Resume' button. + pause = False + resume = False + + selected = component.get('TorrentView').get_selected_torrents() + if not selected: + selected = [] + + for torrent in selected: + try: + status = component.get("TorrentView").get_torrent_status(torrent)['state'] + except KeyError, e: + log.debug("Error getting torrent state: %s", e) + continue + if status == "Paused" or status == "Error": + resume = True + else: + pause = True + if pause and resume: + break + + # Enable the 'Remove Torrent' button only if there's some selected + # torrent. + remove = (len(selected) > 0) + + for name, sensitive in (("toolbutton_pause", pause), + ("toolbutton_resume", resume), + ("toolbutton_remove", remove)): + self.window.main_glade.get_widget(name).set_sensitive(sensitive) + + + return False + + pause = False + resume = False + if action == "paused": + pause = False + resume = True + elif action == "resumed": + pause = True + resume = False + selected = component.get('TorrentView').get_selected_torrents() + if torrent_id == None or (torrent_id in selected and len(selected) == 1): + self.window.main_glade.get_widget("toolbutton_pause").set_sensitive(pause) + self.window.main_glade.get_widget("toolbutton_resume").set_sensitive(resume) + else: + self.update_buttons() + + return False diff --git a/deluge/ui/gtkui/torrentdetails.py b/deluge/ui/gtkui/torrentdetails.py new file mode 100644 index 000000000..988e5f7c0 --- /dev/null +++ b/deluge/ui/gtkui/torrentdetails.py @@ -0,0 +1,309 @@ +# +# torrentdetails.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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. + +"""The torrent details component shows info about the selected torrent.""" + +import gtk, gtk.glade +import os +import os.path +import cPickle + +import deluge.component as component +from deluge.ui.client import aclient as client +from deluge.configmanager import ConfigManager + +from deluge.log import LOG as log + +class Tab: + def __init__(self): + pass + + def get_name(self): + return self._name + + def get_child_widget(self): + parent = self._child_widget.get_parent() + if parent is not None: + parent.remove(self._child_widget) + + return self._child_widget + + def get_tab_label(self): + parent = self._tab_label.get_parent() + if parent is not None: + parent.remove(self._tab_label) + + return self._tab_label + +class TorrentDetails(component.Component): + def __init__(self): + component.Component.__init__(self, "TorrentDetails", interval=2000) + self.window = component.get("MainWindow") + glade = self.window.main_glade + + self.notebook = glade.get_widget("torrent_info") + + # This is the menu item we'll attach the tabs checklist menu to + self.menu_tabs = glade.get_widget("menu_tabs") + + self.notebook.connect("switch-page", self._on_switch_page) + + # Tab index is a list of tab names in the order which they presented + # to the user. + self.tab_index = [] + + # Tabs holds references to the Tab objects by their name + self.tabs = {} + + # tab_name: (tab_object, position) + self.hidden_tabs = {} + + # Add the default tabs + from statistics_tab import StatisticsTab + from details_tab import DetailsTab + from files_tab import FilesTab + from peers_tab import PeersTab + from options_tab import OptionsTab + + default_tabs = { + "Statistics": StatisticsTab, + "Details": DetailsTab, + "Files": FilesTab, + "Peers": PeersTab, + "Options": OptionsTab + } + + default_order = [ + "Statistics", + "Details", + "Files", + "Peers", + "Options" + ] + + # Get the state from saved file + state = self.load_state() + + # The state is a list of tab_names in the order they should appear + if state == None: + # Set the default order + state = default_order + + # Add the tabs in the order from the state + for tab_name in state: + self.add_tab(default_tabs[tab_name]()) + + if len(state) < len(default_order): + # We have hidden tabs and need to add them to the hidden_tabs dict + for i, tab_name in enumerate(default_order): + if tab_name not in state: + self.hidden_tabs[tab_name] = (default_tabs[tab_name](), i) + + # Generate the checklist menu + self.generate_menu() + + def add_tab(self, tab_object, position=-1, generate_menu=True): + """Adds a tab object to the notebook.""" + self.tabs[tab_object.get_name()] = tab_object + pos = self.notebook.insert_page( + tab_object.get_child_widget(), + tab_object.get_tab_label(), + position) + self.tab_index.insert(pos, tab_object.get_name()) + if generate_menu: + self.generate_menu() + + if not self.notebook.get_property("visible"): + # If the notebook isn't visible, show it + self.visible(True) + + def remove_tab(self, tab_name): + """Removes a tab by name.""" + index = self.tab_index.index(tab_name) + self.notebook.remove_page(index) + del self.tabs[tab_name] + del self.tab_index[index] + self.generate_menu() + + # If there are no tabs visible, then do not show the notebook + if len(self.tabs) == 0: + self.visible(False) + + def generate_menu(self): + """Generates the checklist menu for all the tabs and attaches it""" + menu = gtk.Menu() + # Create 'All' menuitem and a separator + menuitem = gtk.CheckMenuItem("All") + menuitem.connect("toggled", self._on_menuitem_toggled) + if len(self.hidden_tabs) > 0: + menuitem.set_active(False) + else: + menuitem.set_active(True) + + menu.append(menuitem) + + menuitem = gtk.SeparatorMenuItem() + menu.append(menuitem) + + # Add all the tabs to the menu + for tab in self.tab_index: + menuitem = gtk.CheckMenuItem(tab) + menuitem.connect("toggled", self._on_menuitem_toggled) + menuitem.set_active(True) + menu.append(menuitem) + + # Add all hidden_tabs to the menu too + for tab in self.hidden_tabs.keys(): + menuitem = gtk.CheckMenuItem(tab) + menuitem.connect("toggled", self._on_menuitem_toggled) + menuitem.set_active(False) + # Try to keep position in sync + menu.insert(menuitem, self.hidden_tabs[tab][1] + 2) + + self.menu_tabs.set_submenu(menu) + self.menu_tabs.show_all() + + def visible(self, visible): + if visible: + self.notebook.show() + else: + self.notebook.hide() + self.window.vpaned.set_position(-1) + + def set_tab_visible(self, tab_name, visible): + """Sets the tab to visible""" + log.debug("set_tab_visible name: %s visible: %s", tab_name, visible) + if visible: + # We need to show tab, make sure it's not already shown + if tab_name not in self.hidden_tabs.keys(): + return + # Add the tab back to the notebook + self.add_tab(self.hidden_tabs[tab_name][0], self.hidden_tabs[tab_name][1], generate_menu=False) + del self.hidden_tabs[tab_name] + else: + # Check to see if tab is already hidden + if tab_name in self.hidden_tabs.keys(): + return + # Remove the tab from the notebook and store it in hidden_tabs + self.hidden_tabs[tab_name] = (self.tabs[tab_name], self.tab_index.index(tab_name)) + self.remove_tab(tab_name) + + def stop(self): + # Save the state of the tabs + for tab in self.tabs: + try: + self.tabs[tab].save_state() + except AttributeError: + pass + + self.clear() + # Save tabs state + self.save_state() + + def update(self, page_num=None): + if len(component.get("TorrentView").get_selected_torrents()) == 0: + # No torrents selected, so just clear + self.clear() + + if self.notebook.get_property("visible"): + if page_num == None: + page_num = self.notebook.get_current_page() + try: + # Get the tab name + name = self.tab_index[page_num] + except IndexError: + return + # Update the tab that is in view + self.tabs[name].update() + + def clear(self): + # Get the tab name + try: + name = self.tab_index[self.notebook.get_current_page()] + self.tabs[name].clear() + except Exception, e: + log.debug("Unable to clear torrentdetails: %s", e) + + def _on_switch_page(self, notebook, page, page_num): + self.update(page_num) + client.force_call(False) + + def _on_menuitem_toggled(self, widget): + # Get the tab name + name = widget.get_child().get_text() + if name == "All": + if self.menu_tabs.get_submenu() is not None: + # Widget has been changed to active which means we need to + # show all the tabs. + for tab in self.menu_tabs.get_submenu().get_children(): + if isinstance(tab, gtk.SeparatorMenuItem): + continue + if tab.get_child().get_text() == "All" or tab is gtk.SeparatorMenuItem: + continue + + tab.set_active(widget.get_active()) + return + + self.set_tab_visible(name, widget.get_active()) + + def save_state(self): + """We save the state, which is basically the tab_index list""" + filename = "tabs.state" + state = self.tab_index + + # Get the config location for saving the state file + config_location = ConfigManager("gtkui.conf")["config_location"] + + try: + log.debug("Saving TorrentDetails state file: %s", filename) + state_file = open(os.path.join(config_location, filename), "wb") + cPickle.dump(state, state_file) + state_file.close() + except IOError, e: + log.warning("Unable to save state file: %s", e) + + def load_state(self): + filename = "tabs.state" + # Get the config location for loading the state file + config_location = ConfigManager("gtkui.conf")["config_location"] + state = None + + try: + log.debug("Loading TorrentDetails state file: %s", filename) + state_file = open(os.path.join(config_location, filename), "rb") + state = cPickle.load(state_file) + state_file.close() + except (EOFError, IOError), e: + log.warning("Unable to load state file: %s", e) + + return state diff --git a/deluge/ui/gtkui/torrentview.py b/deluge/ui/gtkui/torrentview.py new file mode 100644 index 000000000..5dc340462 --- /dev/null +++ b/deluge/ui/gtkui/torrentview.py @@ -0,0 +1,458 @@ +# +# torrentview.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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. + +"""The torrent view component that lists all torrents in the session.""" + +import pygtk +pygtk.require('2.0') +import gtk, gtk.glade +import gettext +import gobject + +import deluge.common +import deluge.component as component +from deluge.ui.client import aclient as client +from deluge.log import LOG as log +import deluge.ui.gtkui.listview as listview + +# Status icons.. Create them from file only once to avoid constantly +# re-creating them. +icon_downloading = gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("downloading16.png")) +icon_seeding = gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("seeding16.png")) +icon_inactive = gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("inactive16.png")) +icon_alert = gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("alert16.png")) +icon_queued = gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("queued16.png")) +icon_checking = gtk.gdk.pixbuf_new_from_file( + deluge.common.get_pixmap("checking16.png")) + +# Holds the info for which status icon to display based on state +ICON_STATE = { + "Allocating": icon_checking, + "Checking": icon_checking, + "Downloading": icon_downloading, + "Seeding": icon_seeding, + "Paused": icon_inactive, + "Error": icon_alert, + "Queued": icon_queued +} + +def cell_data_statusicon(column, cell, model, row, data): + """Display text with an icon""" + try: + icon = ICON_STATE[model.get_value(row, data)] + if cell.get_property("pixbuf") != icon: + cell.set_property("pixbuf", icon) + except KeyError: + pass + +def cell_data_progress(column, cell, model, row, data): + """Display progress bar with text""" + (value, state_str) = model.get(row, *data) + if cell.get_property("value") != value: + cell.set_property("value", value) + + textstr = "%s" % state_str + if state_str != "Seeding" and value < 100: + textstr = textstr + " %.2f%%" % value + if cell.get_property("text") != textstr: + cell.set_property("text", textstr) + +def cell_data_queue(column, cell, model, row, data): + value = model.get_value(row, data) + if value < 0: + cell.set_property("text", "") + else: + cell.set_property("text", value + 1) + +class TorrentView(listview.ListView, component.Component): + """TorrentView handles the listing of torrents.""" + def __init__(self): + component.Component.__init__(self, "TorrentView", interval=2000) + self.window = component.get("MainWindow") + # Call the ListView constructor + listview.ListView.__init__(self, + self.window.main_glade.get_widget("torrent_view")) + log.debug("TorrentView Init..") + # Try to load the state file if available + self.load_state("torrentview.state") + + # This is where status updates are put + self.status = {} + + # Register the columns menu with the listview so it gets updated + # accordingly. + self.register_checklist_menu( + self.window.main_glade.get_widget("menu_columns")) + + # Add the columns to the listview + self.add_text_column("torrent_id", hidden=True) + self.add_bool_column("filter", hidden=True) + self.add_bool_column("dirty", hidden=True) + self.add_func_column("#", cell_data_queue, [int], status_field=["queue"]) + self.add_texticon_column(_("Name"), status_field=["state", "name"], + function=cell_data_statusicon) + self.add_func_column(_("Size"), + listview.cell_data_size, + [gobject.TYPE_UINT64], + status_field=["total_size"]) + self.add_progress_column(_("Progress"), + status_field=["progress", "state"], + col_types=[float, str], + function=cell_data_progress) + self.add_func_column(_("Seeders"), + listview.cell_data_peer, + [int, int], + status_field=["num_seeds", + "total_seeds"]) + self.add_func_column(_("Peers"), + listview.cell_data_peer, + [int, int], + status_field=["num_peers", + "total_peers"]) + self.add_func_column(_("Down Speed"), + listview.cell_data_speed, + [float], + status_field=["download_payload_rate"]) + self.add_func_column(_("Up Speed"), + listview.cell_data_speed, + [float], + status_field=["upload_payload_rate"]) + self.add_func_column(_("ETA"), + listview.cell_data_time, + [int], + status_field=["eta"]) + self.add_func_column(_("Ratio"), + listview.cell_data_ratio, + [float], + status_field=["ratio"]) + self.add_func_column(_("Avail"), + listview.cell_data_ratio, + [float], + status_field=["distributed_copies"]) + + # Set default sort column to # + self.liststore.set_sort_column_id(self.get_column_index("#"), gtk.SORT_ASCENDING) + + # Set filter to None for now + self.filter = (None, None) + + self.create_model_filter() + + ### Connect Signals ### + # Connect to the 'button-press-event' to know when to bring up the + # torrent menu popup. + self.treeview.connect("button-press-event", + self.on_button_press_event) + # Connect to the 'changed' event of TreeViewSelection to get selection + # changes. + self.treeview.get_selection().connect("changed", + self.on_selection_changed) + + def start(self): + """Start the torrentview""" + # We need to get the core session state to know which torrents are in + # the session so we can add them to our list. + client.get_session_state(self._on_session_state) + + def create_model_filter(self): + """create new filter-model + must be called after listview.create_new_liststore + """ + # Set the liststore filter column + model_filter = self.liststore.filter_new() + model_filter.set_visible_column( + self.columns["filter"].column_indices[0]) + self.model_filter = gtk.TreeModelSort(model_filter) + self.treeview.set_model(self.model_filter) + + + def _on_session_state(self, state): + for torrent_id in state: + self.add_row(torrent_id) + + self.update_filter() + self.update() + + def stop(self): + """Stops the torrentview""" + # We need to clear the liststore + self.liststore.clear() + + def shutdown(self): + """Called when GtkUi is exiting""" + self.save_state("torrentview.state") + + def set_filter(self, field, condition): + """Sets filters for the torrentview..""" + if self.filter != (None, None): + self.filter = (None, None) + self.update_filter() + + self.filter = (field, condition) + self.update_filter() + self.update() + + def send_status_request(self, columns=None): + # Store the 'status_fields' we need to send to core + status_keys = [] + # Store the actual columns we will be updating + self.columns_to_update = [] + + if columns is None: + # We need to iterate through all columns + columns = self.columns.keys() + + # Iterate through supplied list of columns to update + for column in columns: + # Make sure column is visible and has 'status_field' set. + # If not, we can ignore it. + if self.columns[column].column.get_visible() is True \ + and self.columns[column].hidden is False \ + and self.columns[column].status_field is not None: + for field in self.columns[column].status_field: + status_keys.append(field) + self.columns_to_update.append(column) + + # Remove duplicate keys + self.columns_to_update = list(set(self.columns_to_update)) + + # If there is nothing in status_keys then we must not continue + if status_keys is []: + return + + # Remove duplicates from status_key list + status_keys = list(set(status_keys)) + + # Create list of torrent_ids in need of status updates + torrent_ids = [] + for row in self.liststore: + # Only add this torrent_id if it's not filtered + if row[self.columns["filter"].column_indices[0]] == True or \ + row[self.columns["dirty"].column_indices[0]] == True : + torrent_ids.append(row[self.columns["torrent_id"].column_indices[0]]) + row[self.columns["dirty"].column_indices[0]] = False + + if torrent_ids == []: + return + + # Request the statuses for all these torrent_ids, this is async so we + # will deal with the return in a signal callback. + client.get_torrents_status( + self._on_get_torrents_status, torrent_ids, status_keys) + + def update_filter(self): + # Update the filter view + for row in self.liststore: + self.update_filter_row(row) + + def update_filter_row(self, row): + filter_column = self.columns["filter"].column_indices[0] + # Create a function to create a new liststore with only the + # desired rows based on the filter. + field, condition = self.filter + if field == None and condition == None: + row[filter_column] = True + return + + value = row[self.get_state_field_column(field)] + + # Condition is True, so lets show this row, if not we hide it + if value == condition: + row[filter_column] = True + else: + row[filter_column] = False + + def update(self): + # Send a status request + self.send_status_request() + + def update_view(self, columns=None): + """Update the view. If columns is not None, it will attempt to only + update those columns selected. + """ + # Update the torrent view model with data we've received + status = self.status + for row in self.liststore: + torrent_id = row[self.columns["torrent_id"].column_indices[0]] + if torrent_id in status.keys(): + # Set values for each column in the row + for column in self.columns_to_update: + column_index = self.get_column_index(column) + if type(column_index) is not list: + # We only have a single list store column we need to + # update + try: + # Only update if different + if row[column_index] != \ + status[torrent_id][self.columns[column].status_field[0]]: + row[column_index] = status[torrent_id][ + self.columns[column].status_field[0]] + except (TypeError, KeyError), e: + log.warning("Unable to update column %s: %s", + column, e) + else: + # We have more than 1 liststore column to update + for index in column_index: + # Only update the column if the status field exists + try: + # Only update if different + if row[index] != \ + status[torrent_id][ + self.columns[column].status_field[ + column_index.index(index)]]: + + row[index] = \ + status[torrent_id][ + self.columns[column].status_field[ + column_index.index(index)]] + except: + pass + self.update_filter_row(row) + # Update the toolbar buttons just in case some state has changed + component.get("ToolBar").update_buttons() + component.get("MenuBar").update_menu() + + def _on_get_torrents_status(self, status): + """Callback function for get_torrents_status(). 'status' should be a + dictionary of {torrent_id: {key, value}}.""" + if status != None: + self.status = status + else: + self.status = {} + + if self.status != {}: + self.update_view() + + def add_row(self, torrent_id): + """Adds a new torrent row to the treeview""" + # Insert a new row to the liststore + row = self.liststore.append() + # Store the torrent id + self.liststore.set_value( + row, + self.columns["torrent_id"].column_indices[0], + torrent_id) + self.update() + self.update_filter() + + def remove_row(self, torrent_id): + """Removes a row with torrent_id""" + for row in self.liststore: + if row[0] == torrent_id: + self.liststore.remove(row.iter) + # Force an update of the torrentview + self.update() + self.update_filter() + break + + def mark_dirty(self, torrent_id = None): + for row in self.liststore: + if not torrent_id or row[0] == torrent_id: + log.debug("marking %s dirty", torrent_id) + row[self.columns["dirty"].column_indices[0]] = True + if torrent_id: break + + def get_selected_torrent(self): + """Returns a torrent_id or None. If multiple torrents are selected, + it will return the torrent_id of the first one.""" + selected = self.get_selected_torrents() + if selected: + return selected[0] + else: + return selected + + def get_selected_torrents(self): + """Returns a list of selected torrents or None""" + torrent_ids = [] + try: + paths = self.treeview.get_selection().get_selected_rows()[1] + except AttributeError: + # paths is likely None .. so lets return [] + return [] + try: + for path in paths: + try: + row = self.model_filter.get_iter(path) + except Exception, e: + log.debug("Unable to get iter from path: %s", e) + continue + + child_row = self.model_filter.convert_iter_to_child_iter(None, row) + child_row = self.model_filter.get_model().convert_iter_to_child_iter(child_row) + if self.liststore.iter_is_valid(child_row): + try: + value = self.liststore.get_value(child_row, 0) + except Exception, e: + log.debug("Unable to get value from row: %s", e) + else: + torrent_ids.append(value) + if len(torrent_ids) == 0: + return [] + + return torrent_ids + except ValueError, TypeError: + return [] + + def get_torrent_status(self, torrent_id): + """Returns data stored in self.status, it may not be complete""" + try: + return self.status[torrent_id] + except: + return {} + + def get_visible_torrents(self): + return self.status.keys() + + ### Callbacks ### + def on_button_press_event(self, widget, event): + """This is a callback for showing the right-click context menu.""" + log.debug("on_button_press_event") + # We only care about right-clicks + if self.get_selected_torrents() and event.button == 3: + # Show the Torrent menu from the MenuBar + torrentmenu = component.get("MenuBar").torrentmenu + torrentmenu.popup(None, None, None, event.button, event.time) + return True + + def on_selection_changed(self, treeselection): + """This callback is know when the selection has changed.""" + log.debug("on_selection_changed") + component.get("TorrentDetails").update() + component.get("ToolBar").update_buttons() + component.get("MenuBar").update_menu() + diff --git a/deluge/ui/null/__init__.py b/deluge/ui/null/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/deluge/ui/null/deluge_shell.py b/deluge/ui/null/deluge_shell.py new file mode 100755 index 000000000..8dd7091ee --- /dev/null +++ b/deluge/ui/null/deluge_shell.py @@ -0,0 +1,499 @@ +#!/usr/bin/env python + +""" +deluge-shell: Deluge shell. +""" + +# deluge-shell: Deluge shell. +# +# Copyright (C) 2007, 2008 Sadrul Habib Chowdhury +# +# This application is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This application 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this application; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 +# USA + +from deluge.ui.client import aclient as client +import deluge.common as common +import deluge.error +import readline +import logging +import gobject + +import sys + +class Enumerate(object): + def __init__(self, names): + for number, name in enumerate(names.split()): + setattr(self, name, number) + +NORMAL = chr(27) + '[00;00m' +NORMAL_B = chr(27) + '[01m' +RED = chr(27) + '[00;31m' +RED_B = chr(27) + '[01;31m' +GREEN = chr(27) + '[00;32m' +GREEN_B = chr(27) + '[01;32m' +YELLOW = chr(27) + '[00;33m' +YELLOW_B = chr(27) + '[01;33m' +BLUE = chr(27) + '[00;34m' +BLUE_B = chr(27) + '[01;34m' +MAGENTA = chr(27) + '[00;35m' +MAGENTA_B = chr(27) + '[01;35m' +CYAN = chr(27) + '[01;36m' +CYAN_B = chr(27) + '[01;36m' + +COLORS = Enumerate('RED GREEN YELLOW BLUE MAGENTA CYAN DEFAULT') +ATTRS = Enumerate('BOLD NORMAL') + +def ATTR(color, attr, str): + ret = chr(27) + '[' + if attr == ATTRS.BOLD: + ret = ret + "01" + else: + ret = ret + "02" + + colormaps = { + COLORS.RED : "31", + COLORS.GREEN : "32", + COLORS.YELLOW : "33", + COLORS.BLUE : "34", + COLORS.MAGENTA : "35", + COLORS.CYAN : "36", + COLORS.DEFAULT : "39" + } + + if color in colormaps: + ret = ret + ";" + colormaps[color] + ret = ret + "m" + return ret + str + chr(27) + "[0m" + +status_keys = ["state", + "save_path", + "tracker", + "next_announce", + "name", + "total_size", + "progress", + "num_seeds", + "total_seeds", + "num_peers", + "total_peers", + "eta", + "download_payload_rate", + "upload_payload_rate", + "ratio", + "distributed_copies", + "num_pieces", + "piece_length", + "total_done", + "files", + "file_priorities", + "file_progress", + "peers", + "is_seed", + ] + +class Command: + def __init__(self): + pass + + def execute(self, cmd): + pass + + def usage(self): + print "" + + def help(self): + pass + + def match_torrents(self, array): + torrents = [] + def _got_session_state(tors): + if not array or len(array) == 0: + for tor in tors: + torrents.append(tor) + return + for match in array: + for tor in tors: + if match == tor[0:len(match)]: + torrents.append(tor) + break + client.get_session_state(_got_session_state) + client.force_call() + return torrents + +class CommandAdd(Command): + """Command to add a torrent.""" + def execute(self, cmd): + if len(cmd) < 2: + self.usage() + return + + save_path = None + readpath = False + if cmd[1] == '-p': + if len(cmd) < 4: + self.usage() + return + del cmd[1] + readpath = True + else: + def _got_config(configs): + global save_path + save_path = configs['download_location'] + client.get_config(_got_config) + client.force_call() + + command = " ".join(cmd[1:]) + paths = command.split(';') + if readpath: + save_path = paths[0].strip() # Perhaps verify that the path exists? + client.set_config({'download_location': save_path}) + del paths[0] + + if not save_path: + print "There's no save-path specified. You must specify a path to save the downloaded files.\n" + return + + for iter in range(0, len(paths)): + paths[iter] = paths[iter].strip() + if len(paths[iter]) == 0: + del paths[iter] + + try: + client.add_torrent_file(paths) + except Exception, msg: + print "*** Error:", str(msg), "\n" + + def usage(self): + print "Usage: add [-p ;] ; [; ...]" + print " (Note that a ';' must follow a path)" + print "" + + def help(self): + print "Add a torrent" + +class CommandConfig(Command): + def execute(self, cmd): + del cmd[0] + def _on_get_config(config): + keys = config.keys() + keys.sort() + for key in keys: + if cmd and key not in cmd: continue + color = NORMAL + value = config[key] + if isinstance(value, bool): + color = YELLOW + elif isinstance(value, int) or isinstance(value, float): + color = GREEN + elif isinstance(value, str): + color = CYAN + elif isinstance(value, list): + color = MAGENTA + + print ("* " + BLUE_B + "%s:" + color + " %s" + NORMAL) % (key, value) + client.get_config(_on_get_config) + + def usage(self): + print "Usage: configs [key1 [key2 ...]]" + print "" + + def help(self): + print "Show configuration values" + +class CommandConfigSet(Command): + def execute(self, cmd): + key = cmd[1] + + # Returns (correct_type, type_value) + def convert_type(target, source): + if isinstance(source, list): + return False, None + + if isinstance(source, bool): + # Because every non-empty string becomes 'True' + if target in ["True", "true", "1"]: + return True, True + elif target in ["False", "false", "0"]: + return True, False + return False, None + + try: + val = type(source)(target) + return True, val + except: + pass + return False, None + + def update_config_value(value, config_val): + if config_val == None: + print RED + "* Invalid configuration name '%s'" % key + NORMAL + return + success, value = convert_type(value, config_val) + if not success: + print RED + "* Configuration value provided has incorrect type." + NORMAL + else: + client.set_config({key: value}) + client.force_call() + print GREEN + "* Configuration value successfully updated." + NORMAL + return False + + def _got_config_value(config_val): + global c_val + c_val = config_val + + value = " ".join(cmd[2:]) + client.get_config_value(_got_config_value, key) + client.force_call() + update_config_value(value, c_val) + + def help(self): + print "Change a configuration setting" + + def usage(self): + print "Usage: config-set key value" + +class CommandExit(Command): + def execute(self, cmd): + print "Thanks" + sys.exit(0) + + def help(self): + print "Exit from the client." + +class CommandHelp(Command): + def execute(self, cmd): + if len(cmd) < 2: + print NORMAL_B + "Available commands:" + NORMAL + for cmd in sorted(commands.keys()): + print "\t*", "%s:" % (BLUE_B + cmd + NORMAL), + command = commands[cmd] + command.help() + else: + for c in cmd[1:]: + if c not in commands: + print RED + "Unknown command:", c + NORMAL + else: + print "*", "%s:" % (BLUE_B + c + NORMAL), + command = commands[c] + command.help() + print GREEN, + command.usage() + print NORMAL, + + def usage(self): + print "Usage: help [cmd1 [cmd2 ...]]" + print "" + + def help(self): + print "Show help" + +class CommandInfo(Command): + def execute(self, cmd): + brief = (len(cmd) < 2) + torrents = self.match_torrents(cmd[1:]) + for tor in torrents: + self.show_info(tor, brief) + + def usage(self): + print "Usage: info [ [ ...]]" + print " You can give the first few characters of a torrent-id to identify the torrent." + print "" + + def help(self): + print "Show information about the torrents" + + def show_info(self, torrent, brief): + def _got_torrent_status(state): + print ATTR(COLORS.BLUE, ATTRS.BOLD, "*** ID:"), torrent + print ATTR(COLORS.BLUE, ATTRS.BOLD, "*** Name:"), state['name'] + print ATTR(COLORS.BLUE, ATTRS.BOLD, "*** Path:"), state['save_path'] + + if not state['is_seed']: + print ATTR(COLORS.GREEN, 0, "*** Completed:"), common.fsize(state['total_done']) + "/" + common.fsize(state['total_size']) + print ATTR(COLORS.GREEN, 0, "*** Status:"), state['state'] + + state['state_i'] = common.TORRENT_STATE.index(state['state']) + if state['state_i'] == 2: # Downloading + print ATTR(COLORS.GREEN, 0, "*** Download Speed:"), common.fspeed(state['download_payload_rate']) + if state['state_i'] in [2, 3]: # Downloading, or Seeding + print ATTR(COLORS.GREEN, 0, "*** Upload Speed:"), common.fspeed(state['upload_payload_rate']) + if state['state_i'] == 2: # Downloading + print ATTR(COLORS.GREEN, 0, "*** ETA:"), "%s" % common.ftime(state['eta']) + + if brief == False: + print ATTR(COLORS.DEFAULT, ATTRS.BOLD, "*** Seeders:"), "%s (%s)" % (state['num_seeds'], state['total_seeds']) + print ATTR(COLORS.DEFAULT, ATTRS.BOLD, "*** Peers:"), "%s (%s)" % (state['num_peers'], state['total_peers']) + print ATTR(COLORS.DEFAULT, ATTRS.BOLD, "*** Share Ratio:"), "%.1f" % state['ratio'] + print ATTR(COLORS.DEFAULT, ATTRS.BOLD, "*** Availability:"), "%.1f" % state['distributed_copies'] + print ATTR(COLORS.CYAN, ATTRS.BOLD, "*** Files:") + for i, file in enumerate(state['files']): + status = "" + if not state['is_seed']: + if state['file_priorities'][i] == 0: + status = " - Do not download" + else: + status = " - %1.f%% completed" % (state['file_progress'][i] * 100) + print "\t* %s (%s)%s" % (file['path'], common.fsize(file['size']), status) + + print ATTR(COLORS.MAGENTA, ATTRS.BOLD, "*** Peers:") + if len(state['peers']) == 0: + print "\t* None" + for peer in state['peers']: + print ("\t*" + BLUE_B + " %-21s" + GREEN_B + " %-25s " + CYAN + "Up: %-12s" + MAGENTA_B + " Down: %-12s" + NORMAL) % \ + (peer['ip'], peer['client'] + ["", " (seed)"][not not peer['seed']], + common.fspeed(peer['up_speed']), common.fspeed(peer['down_speed'])) + print "" + client.get_torrent_status(_got_torrent_status, torrent, status_keys) + +class CommandPause(Command): + def execute(self, cmd): + if len(cmd) < 2: + self.usage() + return + try: + torrents = self.match_torrents(cmd[1:]) + client.pause_torrent(torrents) + except Exception, msg: + print "Error:", str(msg), "\n" + + def usage(self): + print "Usage: pause [ ...]" + print "" + + def help(self): + print "Pause a torrent" + +class CommandResume(Command): + def execute(self, cmd): + if len(cmd) < 2: + self.usage() + return + try: + torrents = self.match_torrents(cmd[1:]) + client.resume_torrent(torrents) + except Exception, msg: + print "Error:", str(msg), "\n" + + def usage(self): + print "Usage: resume [ ...]" + print "" + + def help(self): + print "Resume a torrent" + +class CommandRemove(Command): + def execute(self, cmd): + if len(cmd) < 2: + self.usage() + return + try: + torrents = self.match_torrents(cmd[1:]) + client.remove_torrent(torrents, False, False) + except Exception, msg: + print "*** Error:", str(msg), "\n" + + def usage(self): + print "Usage: rm " + print "" + + def help(self): + print "Remove a torrent" + +class CommandHalt(Command): + def execute(self, cmd): + client.shutdown() + + def help(self): + print "Shutdown the deluge server." + +class CommandConnect(Command): + def execute(self, cmd): + host = 'localhost' + port = 58846 + if len(cmd) > 1: + host = cmd[1] + if len(cmd) > 2: + port = int(cmd[2]) + + if host[:7] != "http://": + host = "http://" + host + + client.set_core_uri("%s:%d" % (host, port)) + + def usage(self): + print "Usage: connect [ []]" + print " 'localhost' is the default server. 58846 is the default port." + print "" + + def help(self): + print "Connect to a new deluge server." + +commands = { + 'add' : CommandAdd(), + 'configs' : CommandConfig(), + 'config-set' : CommandConfigSet(), + 'exit' : CommandExit(), + 'help' : CommandHelp(), + 'info' : CommandInfo(), + 'pause' : CommandPause(), + 'quit' : CommandExit(), + 'resume' : CommandResume(), + 'rm' : CommandRemove(), + 'del' : CommandRemove(), + 'halt' : CommandHalt(), + 'connect' : CommandConnect(), +} + +logging.disable(logging.ERROR) +client.set_core_uri("http://localhost:58846") + +class NullUI: + def __init__(self, args): + print "Welcome to deluge-shell. Type 'help' to see a list of available commands." + + readline.read_init_file() + + while True: + try: + inp = raw_input("> ").strip() + except: + inp = 'quit' + + if len(inp) == 0: continue + inp = inp.split(" ") + + print "" + cmd = inp[0] + found = False + if cmd not in commands: + print RED + "Invalid command!" + NORMAL + commands['help'].execute([]) + else: + command = commands[cmd] + try: + command.execute(inp) + client.force_call() + except deluge.error.NoCoreError, e: + print "*** Operation failed. You are not connected to a deluge daemon." + print " Perhaps you want to 'connect' first." + print "" + #except deluge.error.InvalidTorrent, e: + # print "*** Operation failed. You tried to perform an operation on a non-existent torrent." + # print " Use the 'info' command for the list of torrents." + # print "" + print + + print "Thanks." + diff --git a/deluge/ui/signalreceiver.py b/deluge/ui/signalreceiver.py new file mode 100644 index 000000000..dce443077 --- /dev/null +++ b/deluge/ui/signalreceiver.py @@ -0,0 +1,157 @@ +# +# signalreceiver.py +# +# Copyright (C) 2007, 2008 Andrew Resch ('andar') +# +# 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 2 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 socket +import random + +import gobject + +from deluge.ui.client import aclient as client +import deluge.SimpleXMLRPCServer as SimpleXMLRPCServer +from SocketServer import ThreadingMixIn +import deluge.xmlrpclib as xmlrpclib +import threading +import socket + +from deluge.log import LOG as log + +class SignalReceiver(ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer): + + def __init__(self): + log.debug("SignalReceiver init..") + # gobject.threads_init() + + # Set to true so that the receiver thread will exit + self._shutdown = False + + self.signals = {} + self.emitted_signals = [] + + self.remote = False + + + def shutdown(self): + """Shutdowns receiver thread""" + self._shutdown = True + # De-register with the daemon so it doesn't try to send us more signals + try: + client.deregister_client() + client.force_call() + except Exception, e: + log.debug("Unable to deregister client from server: %s", e) + + log.debug("Shutting down signalreceiver") + + self.socket.shutdown(socket.SHUT_RDWR) + log.debug("Joining listening thread..") + self.listening_thread.join(1.0) + return + + def set_remote(self, remote): + self.remote = remote + + def run(self): + """This gets called when we start the thread""" + host = "localhost" + if self.remote == True: + host = "" + + # Setup the xmlrpc server + server_ready = False + while not server_ready: + port = random.randint(40000, 65535) + try: + SimpleXMLRPCServer.SimpleXMLRPCServer.__init__( + self, (host, port), logRequests=False, allow_none=True) + except socket.error, e: + log.debug("Trying again with another port: %s", e) + except: + log.error("Could not start SignalReceiver XMLRPC server: %s", e) + sys.exit(0) + else: + self.port = port + server_ready = True + + # Register the emit_signal function + self.register_function(self.emit_signal) + + # Register the signal receiver with the core + client.register_client(str(self.port)) + + self.listening_thread = threading.Thread(target=self.handle_thread) + + gobject.timeout_add(50, self.handle_signals) + + try: + self.listening_thread.start() + except Exception, e: + log.debug("Thread: %s", e) + + def handle_thread(self): + try: + while not self._shutdown: + self.handle_request() + self._shutdown = False + except Exception, e: + log.debug("handle_thread: %s", e) + + def get_port(self): + """Get the port that the SignalReceiver is listening on""" + return self.port + + def emit_signal(self, signal, *data): + """Exported method used by the core to emit a signal to the client""" + self.emitted_signals.append((signal, data)) + return + + def handle_signals(self): + for signal, data in self.emitted_signals: + try: + for callback in self.signals[signal]: + gobject.idle_add(callback, *data) + + except Exception, e: + log.warning("Unable to call callback for signal %s: %s", signal, e) + + self.emitted_signals = [] + return True + + def connect_to_signal(self, signal, callback): + """Connect to a signal""" + try: + if callback not in self.signals[signal]: + self.signals[signal].append(callback) + except KeyError: + self.signals[signal] = [callback] + diff --git a/deluge/ui/ui.py b/deluge/ui/ui.py new file mode 100644 index 000000000..4ab30461c --- /dev/null +++ b/deluge/ui/ui.py @@ -0,0 +1,70 @@ +# +# ui.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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 deluge.configmanager + +from deluge.log import LOG as log + +DEFAULT_PREFS = { + "selected_ui": "gtk" +} + +class UI: + def __init__(self, options, args): + log.debug("UI init..") + + # Set the config directory + deluge.configmanager.set_config_dir(options.config) + + config = deluge.configmanager.ConfigManager("ui.conf", DEFAULT_PREFS) + + if options.ui != None: + config["selected_ui"] = options.ui + + selected_ui = config["selected_ui"] + config.save() + del config + + if selected_ui == "gtk": + log.info("Starting GtkUI..") + from deluge.ui.gtkui.gtkui import GtkUI + ui = GtkUI(args) + elif selected_ui == "web": + log.info("Starting WebUI..") + from deluge.ui.webui.webui import WebUI + ui = WebUI(args) + elif selected_ui == "null": + log.info("Starting NullUI..") + from deluge.ui.null.deluge_shell import NullUI + ui = NullUI(args) + diff --git a/LICENSE b/deluge/ui/webui/LICENSE similarity index 100% rename from LICENSE rename to deluge/ui/webui/LICENSE diff --git a/deluge/ui/webui/TODO b/deluge/ui/webui/TODO new file mode 100644 index 000000000..0fd8a6b53 --- /dev/null +++ b/deluge/ui/webui/TODO @@ -0,0 +1,30 @@ +After labels: +*templates : remove advanced , rename deluge to classic , result = classic-templ -> no-javascript ; white-templ -> static enhanced with js ; ajax-templ -> json api +*white temnplate: add deluge icon. +*fix all comments from IRC-nonicknamename2. + +0.6 RC: +*Fix IE7 for advanced/white template. +*white template : add auto-refresh (with a nice js-progress-bar) +*gettext : update template_strings.py + add all .py files to gettext input files + +after 0.6 /before 1.0: +*hide-option for details iframe. +*white template:better css fluid layout or switch to tables. +*rethink details iframe. +*persistent sessions + +maybe/ideas/after 0.6.1: +*checkboxes for multiple select? +*switch to webpy 0.3 +*right-click menu on torrent-rows +*multi row template like transmission etc. + +Half-done: +*labels (organize-plugin) +*add new major features in available gtk ui but not in webui. + +Done: +*plugin-config + (re)enable webui plugins. +*white-template : green-iframe ->make blue + diff --git a/plugins/NetworkHealth/__init__.py b/deluge/ui/webui/__init__.py similarity index 68% rename from plugins/NetworkHealth/__init__.py rename to deluge/ui/webui/__init__.py index cd5195581..9a24e958f 100644 --- a/plugins/NetworkHealth/__init__.py +++ b/deluge/ui/webui/__init__.py @@ -1,19 +1,18 @@ # -*- coding: utf-8 -*- # -# __init__.py # -# Copyright (C) Marcos Pinto 2007 +# Copyright (C) Martijn Voncken 2007 # # 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 2, 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., @@ -28,21 +27,5 @@ # 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. - -plugin_name = "Network Health Monitor" -plugin_author = "Alon Zakai, Zach Tibbitts" -plugin_version = "0.2" -plugin_description = _("Network Health Monitor plugin\n\nWritten by Kripkenstein") -def deluge_init(deluge_path): - global path - path = deluge_path - - -from NetworkHealth.plugin import plugin_NetworkHealth - -def enable(core, interface): - global path - return plugin_NetworkHealth(path, core, interface) diff --git a/deluge/ui/webui/apache.py b/deluge/ui/webui/apache.py new file mode 100644 index 000000000..b2e211bf2 --- /dev/null +++ b/deluge/ui/webui/apache.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# Copyright (C) Martijn Voncken 2008 +# License: GPL v2(+OpenSSL exception), see LICENSE file in base directory. +""" +this is an ugly hack, and it will be changed. +for experimental use only!! +""" +import os + +def get_wsgi_application(base_url, config_dir): + + #monkeypatch: + from deluge import common + def get_config_dir(filename = ""): + return os.path.join(config_dir, filename) + common.get_config_dir = get_config_dir + #/monkeypatch + + from deluge.configmanager import ConfigManager + from deluge.ui.webui import deluge_webserver + from deluge.ui.webui import utils + + config = ConfigManager("webui06.conf") + + utils.set_config_defaults() + + config.set('base','/deluge') + config.set('disallow',{ + '/daemon/control':'running as an apache user', + '/config/server':'running as an apache-user' + }) + + utils.apply_config() + + return deluge_webserver.WsgiApplication() diff --git a/deluge/ui/webui/components.py b/deluge/ui/webui/components.py new file mode 100644 index 000000000..aad20c0b1 --- /dev/null +++ b/deluge/ui/webui/components.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# +# Copyright (C) Martijn Voncken 2008 +# +# 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 2, 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. +# + +""" +deluge components. + +MenuManager:add torrent-menu-items and torrent-detail tabs. +PageManager: add pages(urls) +PluginManager: deluge plugin manager +ConfigPageManager: add config pages(tabs) + +These managers/components are accesible as: + +from deluge import component +manager = component.get("ClassName") + +""" +from deluge import component +import lib.newforms_plus as forms +from deluge.ui.client import aclient +from deluge import component, pluginmanagerbase +from deluge.configmanager import ConfigManager +from deluge.log import LOG as log + +class TOOLBAR_FLAGS: + generic = 0 + torrent = 1 + torrent_list = 2 + +class MenuManager(component.Component): + TOOLBAR_FLAGS = TOOLBAR_FLAGS + def __init__(self): + component.Component.__init__(self, "MenuManager") + self.admin_pages = [] #[(title, url),..] + self.detail_tabs = [] #[(title, url),..] + self.toolbar_items = [] #((id,title ,flag ,method ,url ,image ),.. ) + + + #register vars in template. + from render import template + template.Template.globals["admin_pages"] = self.admin_pages + template.Template.globals["detail_tabs"] = self.detail_tabs + template.Template.globals["toolbar_items"] = self.toolbar_items + + + def register_toolbar_item(self, id, title, image, flag, method, url, important): + self.toolbar_items.append((id, title, image, flag, method, url, important)) + + def unregister_toolbar_item(self, item_id): + for (i, toolbar) in enumerate(admin_pages): + if toolbar[0] == item_id: + del self.toolbar_items[i] + + #admin: + def register_admin_page(self, id, title, url): + self.admin_pages.append((id, title, url)) + + def unregister_admin_page(page_id): + for (i, (id, title, url)) in list(enumerate(admin_pages)): + if id == page_id: + del self.admin_pages[i] + return + + #detail: + def register_detail_tab(self, id, title, page): + self.detail_tabs.append((id, title, page)) + + def unregister_detail_tab(self, tab_id): + for (i, (id, title, tab)) in list(enumerate(detail_tabs)): + if id == tab_id: + del self.detail_tabs[i] + return + +class PageManager(component.Component): + """ + web,py 0.2 mapping hack.. + see deluge_webserver.py + """ + def __init__(self): + component.Component.__init__(self, "PageManager") + self.page_classes = {} + self.urls = [] + + def register_pages(self, url_list, class_list): + self.urls += url_list + self.page_classes.update(class_list) + + def register_page(self, url, klass): + self.urls.append(url) + self.urls.append(klass.__name__) + self.page_classes[klass.__name__] = klass + + def unregister_page(self, url): + raise NotImplemenetedError() + #self.page_classes[klass.__name__] = None + +class PluginManager(pluginmanagerbase.PluginManagerBase, + component.Component): + def __init__(self): + component.Component.__init__(self, "WebPluginManager") + self.config = ConfigManager("webui06.conf") + pluginmanagerbase.PluginManagerBase.__init__( + self, "webui06.conf", "deluge.plugin.webui") + + def start(self): + """Start the plugin manager""" + # Update the enabled_plugins from the core + log.debug("start pl-manager") + aclient.get_enabled_plugins(self._on_get_enabled_plugins) + aclient.force_call(block=True) + + def stop(self): + # Disable the plugins + self.disable_plugins() + + def _on_get_enabled_plugins(self, enabled_plugins): + + log.debug("..Webui has these plugins enabled: %s", enabled_plugins) + + log.debug("abababab") + log.debug(self.config) + + self.config.config["enabled_plugins"] = enabled_plugins + + # Enable the plugins that are enabled in the config and core + log.debug(self.enable_plugins) + try: + self.enable_plugins() + except Exception, e: + log.debug(e) + + +class ConfigPageManager(component.Component): + def __init__(self): + component.Component.__init__(self, "ConfigPageManager") + self.groups = [] + self.blocks = forms.django.utils.datastructures.SortedDict() + + def register(self, group, name, form): + if not group in self.groups: + self.groups.append(group) + form.group = group + self.blocks[name] = form + + def unregister(self, name): + del self.blocks[name] + +class PluginApi(component.Component): + """ + """ + def __init__(self): + component.Component.__init__(self, "WebPluginApi") + import web + from render import render + import page_decorators as deco + import utils + import lib.newforms_plus as forms + + self.render = render + self.web = web + self.deco = deco + self.forms = forms + self.page_manager = component.get("PageManager") + self.config_page_manager = component.get("ConfigPageManager") + self.menu_manager = component.get("MenuManager") + self.utils = utils + +def register(): + __plugin_manager = PluginManager() + __menu_manager = MenuManager() + __page_manager = PageManager() + __config_page_manager = ConfigPageManager() + __plugin_api = PluginApi() + + + + + + diff --git a/deluge/ui/webui/config_forms.py b/deluge/ui/webui/config_forms.py new file mode 100644 index 000000000..4eaceb9da --- /dev/null +++ b/deluge/ui/webui/config_forms.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) Martijn Voncken 2008 +# +# 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 2, 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. + +import lib.newforms_plus as forms +import page_decorators as deco +import web +from deluge.ui.client import sclient as proxy +from deluge.log import LOG as log + +from render import render +from utils import seeother +import sys +import os +import utils + +from deluge import component +from deluge.configmanager import ConfigManager + +config = ConfigManager("webui06.conf") +config_page_manager = component.get("ConfigPageManager") + +class WebCfgForm(forms.Form): + "config base for webui" + def initial_data(self): + return config.get_config() + + def save(self, data): + for key, value in data.iteritems(): + config.set(key, value) + config.save() + +class CookieCfgForm(forms.Form): + "config base for webui" + def initial_data(self): + return dict(config) + + def save(self, data): + config.update(data) + config.save_config() + + +class CfgForm(forms.Form): + "config base for deluge-cfg" + def initial_data(self): + return proxy.get_config() + def save(self, data): + proxy.set_config(dict(data)) + +class config_page: + """ + web.py config page + """ + def get_form_class(self,name): + try: + return config_page_manager.blocks[name] + except KeyError: + raise Exception('no config page named:"%s"' % name) + + @deco.deluge_page + def GET(self, name): + if name == '': + return seeother('/config/template') + + form_class = self.get_form_class(name) + f = form_class() + f.full_clean() + return self.render(f , name) + + @deco.deluge_page + def POST(self,name): + + form_class = self.get_form_class(name) + form_data = web.Storage(utils.get_newforms_data(form_class)) + form = form_class(form_data) + if form.is_valid(): + log.debug('save config %s' % form_data) + try: + form.start_save() + return self.render(form , name, _('These changes were saved')) + except forms.ValidationError, e: + log.debug(e.message) + return self.render(form , name, error = e.message) + else: + return self.render(form , name, + error= _('Correct the errors above and try again')) + + def render(self, f , name , message = '' , error=''): + return render.config(config_page_manager.groups, config_page_manager.blocks, f, name , message , error) + +def register(): + component.get("PageManager").register_page("/config/(.*)", config_page) + diff --git a/deluge/ui/webui/config_tabs_deluge.py b/deluge/ui/webui/config_tabs_deluge.py new file mode 100644 index 000000000..19988940d --- /dev/null +++ b/deluge/ui/webui/config_tabs_deluge.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +# +# deluge_webserver.py +# +# Copyright (C) Martijn Voncken 2008 +# +# 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 2, 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 deluge.ui.client import sclient +from deluge.log import LOG as log + +import utils + +import lib.newforms_plus as forms +import config_forms +from deluge import component + +config_page = component.get("ConfigPageManager") + +class NetworkPorts(config_forms.CfgForm ): + title = _("Ports") + _port_from = forms.IntegerField(label= _("From"),min_value = 0, max_value=65535) + _port_to = forms.IntegerField(label = _("To"),min_value = 0, max_value=65535) + random_port = forms.CheckBox(label = _("Random")) + + def initial_data(self): + data = config_forms.CfgForm.initial_data(self) + data['_port_from'] , data['_port_to'] = data['listen_ports'] + return data + + def save(self,data): + data['listen_ports'] = [data['_port_from'] , data['_port_to'] ] + del(data['_port_from']) + del(data['_port_to']) + config_forms.CfgForm.save(self, data) + + def validate(self, data): + if (data['_port_to'] < data['_port_from']): + raise forms.ValidationError('"Port from" must be greater than "Port to"') + + def post_html(self): + return """ + + """ % {'active_port':sclient.get_listen_port()} + +config_page.register('network','ports', NetworkPorts) + +class NetworkExtra(config_forms.CfgForm ): + title = _("Extra's") + dht = forms.CheckBox(_("Mainline DHT")) + upnp = forms.CheckBox(_("UpNP")) + natpmp = forms.CheckBox(_("NAT-PMP")) + utpex = forms.CheckBox(_("Peer-Exchange")) + lsd = forms.CheckBox(_("LSD")) + +config_page.register('network','extra', NetworkExtra) + +class NetworkEnc(config_forms.CfgForm ): + title = _("Encryption") + + _enc_choices = list(enumerate([_("Forced"),_("Enabled"),_("Disabled")])) + _level_choices = list(enumerate([_("Handshake"), _("Full") , _("Either")])) + + enc_in_policy = forms.IntChoiceField(_("Inbound"), _enc_choices) + enc_out_policy = forms.IntChoiceField(_("Outbound"), _enc_choices) + enc_level = forms.IntChoiceField(_("Level"), _level_choices) + enc_prefer_rc4 = forms.CheckBox("Prefer to encrypt entire stream") + +config_page.register('network','encryption', NetworkEnc) + + +class BandwithGlobal(config_forms.CfgForm): + title = _("Global") + info = _("-1 = Unlimited") + max_connections_global = forms.DelugeInt(_("Maximum Connections")) + max_download_speed = forms.DelugeFloat(_("Maximum Download Speed (Kib/s)")) + max_upload_speed = forms.DelugeFloat(_("Maximum Upload Speed (Kib/s)")) + max_upload_slots_global = forms.DelugeInt(_("Maximum Upload Slots")) + +config_page.register('bandwidth','global', BandwithGlobal) + +class BandwithTorrent(config_forms.CfgForm): + title = _("Per Torrent") + info = _("-1 = Unlimited") + max_connections_per_torrent = forms.DelugeInt(_("Maximum Connections")) + max_download_speed_per_torrent = forms.DelugeFloat(_("Maximum Download Speed (Kib/s)")) + max_upload_speed_per_torrent = forms.DelugeFloat(_("Maximum Upload Speed (Kib/s)")) + max_upload_slots_per_torrent = forms.DelugeInt(_("Maximum Upload Slots")) + +config_page.register('bandwidth','torrent', BandwithTorrent) + +class Download(config_forms.CfgForm): + title = _("Download") + download_location = forms.ServerFolder(_("Store all downoads in")) + torrentfiles_location = forms.ServerFolder(_("Save .torrent files to")) + autoadd_location = forms.ServerFolder(_("Auto Add folder"), required=False) + compact_allocation = forms.CheckBox(_('Use Compact Allocation')) + prioritize_first_last_pieces = forms.CheckBox(_('Prioritize first and last pieces')) + #default_private = forms.CheckBox(_('Set private flag by default')) + +config_page.register('deluge','download', Download) + +class Daemon(config_forms.CfgForm): + title = _("Daemon") + info = _("Restart daemon and webui after changing these settings") + daemon_port = forms.IntegerField(_("Port")) + allow_remote = forms.CheckBox(_("Allow Remote Connections")) + +config_page.register('deluge','daemon', Daemon) + +class Queue(config_forms.CfgForm): + title = _("Queue") + info = _("-1 = unlimited") + + queue_new_to_top = forms.CheckBox(_("Queue new torrents to top")) + + + #total_downloading = forms.DelugeInt(_("Total active downloading")) + max_active_limit = forms.DelugeInt(_("Total active torrents")) + max_active_downloading = forms.DelugeInt(_("Total active downloading")) + max_active_seeding = forms.DelugeInt(_("Total active seeding")) + + + share_ratio_limit = forms.FloatField(min_value=-1) + seed_time_ratio_limit = forms.FloatField(min_value=-1) + seed_time_limit = forms.FloatField(min_value=-1) + + stop_seed_at_ratio = forms.CheckBox(_("Stop seeding when ratio reaches")) + #stop_ratio = forms.FloatField(min_value=-1) + remove_seed_at_ratio = forms.CheckBox(_("Remove torrent when ratio reached")) + stop_seed_ratio = forms.FloatField(min_value=-1) + +config_page.register('deluge','queue', Queue) + + +class Plugins(forms.Form): + title = _("Enabled Plugins") + + enabled_plugins = forms.LazyMultipleChoice( + choices_getter = lambda: [(p,p) for p in sclient.get_available_plugins()] + ) + + def initial_data(self): + return {'enabled_plugins':sclient.get_enabled_plugins()} + + def save(self, data): + new_plugins = data.enabled_plugins + old_plugins = sclient.get_enabled_plugins() + + enable = [p for p in new_plugins if p not in old_plugins] + disable = [p for p in old_plugins if p not in new_plugins] + + + plugin_manager = component.get("WebPluginManager") + for p in enable: + sclient.enable_plugin(p) + plugin_manager.enable_plugin(p) + + for p in disable: + sclient.disable_plugin(p) + plugin_manager.disable_plugin(p) + + +config_page.register('deluge','plugins', Plugins) + diff --git a/deluge/ui/webui/config_tabs_webui.py b/deluge/ui/webui/config_tabs_webui.py new file mode 100644 index 000000000..5c481d2a5 --- /dev/null +++ b/deluge/ui/webui/config_tabs_webui.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# deluge_webserver.py +# +# Copyright (C) Martijn Voncken 2008 +# +# 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 2, 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 deluge.ui.client import sclient as proxy +from deluge.log import LOG as log + +import utils +import lib.newforms_plus as forms +import config_forms +from deluge import component +from render import render + +config_page = component.get("ConfigPageManager") +plugins = component.get("WebPluginManager") + +class Template(config_forms.WebCfgForm): + title = _("Template") + + _templates = [(t,t) for t in render.get_templates()] + _button_choices = enumerate([_('Text and image'), _('Image Only') + , _('Text Only')]) + + template = forms.ChoiceField( label=_("Template"), choices = _templates) + button_style = forms.IntChoiceField(_("Button style"),_button_choices) + cache_templates = forms.CheckBox(_("Cache templates")) + + def post_save(self): + from render import render + render.apply_cfg() + +class Server(config_forms.WebCfgForm): + title = _("Server") + port = forms.IntegerField(label = _("Port"),min_value=80) + + def post_save(self): + pass + #raise forms.ValidationError( + # _("Manually restart server to apply these changes.")) + +class Password(forms.Form): + title = _("Password") + + old_pwd = forms.Password(_("Current Password")) + new1 = forms.Password(_("New Password")) + new2 = forms.Password(_("New Password (Confirm)")) + + def save(self,data): + utils.update_pwd(data.new1) + + def validate(self, data): + if not utils.check_pwd(data.old_pwd): + raise forms.ValidationError(_("Old password is invalid")) + if data.new1 <> data.new2: + raise forms.ValidationError( + _("New Password is not equal to New Password(confirm)")) + + def post_save(self): + utils.end_session() + #raise forms.ValidationError(_("Password changed,please login again")) + +config_page.register('webui','template', Template) +config_page.register('webui','server',Server) +config_page.register('webui','password',Password) diff --git a/plugins/WebUi/debugerror.py b/deluge/ui/webui/debugerror.py similarity index 88% rename from plugins/WebUi/debugerror.py rename to deluge/ui/webui/debugerror.py index 259dcac72..ad1f3011d 100644 --- a/plugins/WebUi/debugerror.py +++ b/deluge/ui/webui/debugerror.py @@ -1,21 +1,48 @@ """ -pretty debug errors -(part of web.py) +adapted for deluge-webui: +-edit-box with traceback for cut+paste. +-pretty errors for well known exceptions. + +web.py : adapted from Django Copyright (c) 2005, the Lawrence Journal-World Used under the modified BSD license: http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 """ - __all__ = ["debugerror", "djangoerror"] +import utils + +pretty_errors_str = { +"org.freedesktop.DBus.Error.ServiceUnknown": + """ Webui Lost the connection to deluge
+ Unable to reconnect, please restart deluge. + """, +"InvalidUniqueIDError:": + """ + this torrent was removed, +
click here to go to the torrent-list + """ +} + + +pretty_errors_cls = { + type(utils.UnknownTorrentError):""" + this torrent was removed, + click here to go to the torrent-list + """ +} + import sys, urlparse, pprint -from lib.webpy022.net import websafe -from lib.webpy022.template import Template -import lib.webpy022.webapi as web +from web import websafe +from web import template +import web #import lib.webpy022.webapi as web import webserver_common as ws from traceback import format_tb +from deluge import common + +Template = template.Template import os, os.path whereami = os.path.join(os.getcwd(), __file__) @@ -136,7 +163,7 @@ $def with (exception_type, exception_value, frames, exception_message, version_i Oops, Deluge Broke :-( , You might have found a bug, or you did something really stupid ;-).
If the error persists :
- Read the Faq.
+ Read the Faq.
Try downloading the latest version at deluge-torrent.org
Visit the forum @@ -146,7 +173,11 @@ $def with (exception_type, exception_value, frames, exception_message, version_i
-Paste the contents of this text-box when you are asked for a traceback:
+Paste the contents of this text-box when you are asked for a traceback.
+Try to explain what you where doing, +and how you could work around the problem.
+Don't paste without context and expect us to know what went wrong. +
@@ -299,10 +332,18 @@ def djangoerror(): exception_message = 'no message' exception_type = exception_type.__name__ - version_info = ( - "WebUi : rev." + ws.REVNO - + "Python : " + str(sys.version) - ) + """ + for err_str in pretty_errors: + if err_str in exception_message: + #from render import render + return render.error(pretty_errors[err_str]) + """ + if exception_type in pretty_errors_cls: + from render import render + return render.error(pretty_errors_cls[exception_type]) + + version_info = "WebUi : %sr%s\nPython %s:" % ( common.get_version() ,common.get_revision(),sys.version) + try: import dbus version_info += '\ndbus:' + str(dbus.__version__) diff --git a/deluge/ui/webui/deluge_webserver.py b/deluge/ui/webui/deluge_webserver.py new file mode 100644 index 000000000..6c03673a1 --- /dev/null +++ b/deluge/ui/webui/deluge_webserver.py @@ -0,0 +1,124 @@ +# +# Copyright (C) Martijn Voncken 2007 +# +# 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 2, 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. + +import web +import random +import gettext +import locale +from deluge.configmanager import ConfigManager +import pkg_resources +from deluge.ui.client import sclient +import components +from deluge.log import LOG as log + +# Initialize gettext +locale.setlocale(locale.LC_MESSAGES, '') +locale.bindtextdomain("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) +locale.textdomain("deluge") +gettext.bindtextdomain("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) +gettext.textdomain("deluge") +gettext.install("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) + +components.register() #after gettext!! + +from debugerror import deluge_debugerror +from render import render +import utils + + +## Init ## +config = ConfigManager("webui06.conf") +random.seed() +web.webapi.internalerror = deluge_debugerror + +#self registering pages etc. +import pages +import config_tabs_webui #auto registers in ConfigUiManager +import config_tabs_deluge #auto registers in ConfigUiManager +import register_menu #auto registers. +#manual register: +import torrent_add +torrent_add.register() +import torrent_options +torrent_options.register() +import torrent_move +torrent_move.register() +import config_forms +config_forms.register() +import json_api +json_api.register() +#/self registering pages. + + +def WsgiApplication(middleware = None): + from web import webpyfunc, wsgifunc + from deluge import component + + pagemanager = component.get("PageManager") + if not middleware: + middleware = [] + + return wsgifunc(webpyfunc(pagemanager.urls, pagemanager.page_classes, False), *middleware) + +def create_webserver(debug = False): + "starts builtin webserver" + import web + + utils.set_config_defaults() + config.set('base','') + config.set('disallow',{}) + utils.apply_config() + + + from lib.webpy022.wsgiserver import CherryPyWSGIServer + + middleware = None + if debug: + middleware = [web.reloader] + + wsgi_app = WsgiApplication(middleware) + + server_address=("0.0.0.0", int(config.get('port'))) + server = CherryPyWSGIServer(server_address, wsgi_app, server_name="localhost") + + log.info("http://%s:%d/" % server_address) + return server + +def run(debug = False): + server = create_webserver(debug) + try: + server.start() + except KeyboardInterrupt: + server.stop() diff --git a/deluge/ui/webui/json_api.py b/deluge/ui/webui/json_api.py new file mode 100644 index 000000000..692ed0080 --- /dev/null +++ b/deluge/ui/webui/json_api.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# webserver_framework.py +# +# Copyright (C) Martijn Voncken 2008 +# +# 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 2, 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. +""" +json api. + +design: +== Full client api == + * url : /json/rpc/ + * rpc-api : http://en.wikipedia.org/wiki/JSON-RPC + * methods : http://dev.deluge-torrent.org/wiki/Development/UiClient#Remoteapi + +""" +from traceback import format_exc +import web +from web import webapi +import page_decorators as deco +from web import cookies, setcookie as w_setcookie +import utils +from deluge.ui.client import sclient,aclient +from deluge.log import LOG as log +from deluge import component +from utils import dict_cb +from lib import json + + +class json_rpc: + """ + == Full client api == + * url : /json/rpc + * rpc-api : http://en.wikipedia.org/wiki/JSON-RPC#Version_1.0 + * methods : http://dev.deluge-torrent.org/wiki/Development/UiClient#Remoteapi + """ + def GET(self): + print '{"error":"only POST is supported"}' + + + def POST(self , name=None): + web.header("Content-Type", "application/x-json") + ck = cookies() + if not(ck.has_key("session_id") and ck["session_id"] in utils.SESSIONS): + print """{"error":{ + "number":1, + "message":"not authenticated", + "error":"not authenticated" + } + } + """ + return + id = 0 + try: + log.debug("json-data:") + log.debug(webapi.data()) + json_data = json.read(webapi.data()) + id = json_data["id"] + method = json_data["method"] + params = json_data["params"] + + if method.startswith('_'): + raise Exception('_ methods are illegal.') + + if method.startswith("system."): + result = self.exec_system_method(method, params,id) + elif method == ("list_torrents"): + result = self.list_torrents(method, params,id) + elif method == ("get_stats"): + result = self.exec_get_stats(method, params,id) + else: + result = self.exec_client_method(method, params,id) + + log.debug("JSON-result:%s(%s)[%s] = %s" % (method, params, id, result)) + print json.write(result) + + except Exception,e: + #verbose because you don't want exeptions in the error-handler. + message = "" + if hasattr(e,"message"): + message = e.message + log.debug(format_exc()) + log.error("JSON-error:%s:%s %s" % (e, message, id)) + print json.write({ + "version":"1.1", + "id":id, + "error":{ + "number":123, + "message":"%s:%s %s" % (e, message, id), + "error":format_exc() + } + }) + + def exec_client_method(self, method, params, id): + if not hasattr(sclient,method): + raise Exception('Unknown method:%s', method) + + #Call: + func = getattr(sclient, method) + result = func(*params) + + return { + "version":"1.1", + "result":result, + "id":id + } + + def exec_system_method(self, method, params, id): + if method == "system.listMethods": + methods = sclient.list_methods() + return { + "version":"1.1", + "result":methods + ["get_stats"], + "id":id + } + raise Exception('Unknown method:%s', method) + + def exec_get_stats(self, method, params, id): + stats = {} + + aclient.get_download_rate(dict_cb('download_rate',stats)) + aclient.get_upload_rate(dict_cb('upload_rate',stats)) + aclient.get_config_value(dict_cb('max_download',stats) + ,"max_download_speed") + aclient.get_config_value(dict_cb('max_upload',stats) + ,"max_upload_speed") + aclient.get_num_connections(dict_cb("num_connections",stats)) + aclient.get_config_value(dict_cb('max_num_connections',stats) + ,"max_connections_global") + aclient.get_dht_nodes(dict_cb('dht_nodes',stats)) + + aclient.force_call(block=True) + + return { + "version":"1.1", + "result":stats, + "id":id + } + + + + def list_torrents(self,params,id): + """ + == torrent_list == + Composite call. + Goal : limit the number of ajax calls + + filter is only effective if the organize plugin is enabled. + label is redirected to the tracker column, there will be a label feature in the future. + cache_id = future feature, not effective yet. + + === input === + {{{ + { + keys: [], + filter: { + /*ommitted keys are ignored*/ + "keyword":string + "label":string, + "state":string + } , + cache_id: int + } + }}} + + === output === + {{{ + { + torrents: + [ {"id":string,"name":string, ..}, ..] + states: + [('string',int), ..] + trackers: + [('string',int), ..] + stats: + [upload_rate, download_rate, nu_connections, num_dht_nodes] + } + cache_id:int + } + }}} + """ + """filter = params["filter"] + keys = params["keys"] + cache_id = params["cache_id"] + organize_filters = {} + + if 'Organize' in proxy.get_enabled_plugins(): + filter_dict = {} + + for filter_name in ["state","tracker","keyword"]: + value = get(filter,filter_name) + if value and value <> "All": + filter_dict[filter_name] = value + + torrent_ids = proxy.organize_get_session_state(filter_dict) + organize_filters = Storage(proxy.organize_all_filter_items()) + else: + torrent_ids = proxy.get_session_state() + organize_filters = {"state":[["All",-1]],"tracker":[]} + + result = { + "torrents":sclient.get_torrents_status(torrent_ids, keys), + "state":organize_filters["state"], + "tracker":organize_filters["tracker"], + "stats":[0, 1, 2, 3], #todo + "cache_id":cache_id + } + """ + + + +def register(): + component.get("PageManager").register_page("/json/rpc",json_rpc) + +if __name__ == '__main__': + print "todo: tests" diff --git a/deluge/ui/webui/lib/__init__.py b/deluge/ui/webui/lib/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/deluge/ui/webui/lib/json.py b/deluge/ui/webui/lib/json.py new file mode 100644 index 000000000..9bb33d23d --- /dev/null +++ b/deluge/ui/webui/lib/json.py @@ -0,0 +1,815 @@ +#mvoncken 2008: added complete LGPL to this file to ease distribution +import string +import types + +## json.py implements a JSON (http://json.org) reader and writer. +## Copyright (C) 2005 Patrick D. Logan +## Contact mailto:patrickdlogan@stardecisions.com +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library 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 +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! +""" + + +class _StringGenerator(object): + def __init__(self, string): + self.string = string + self.index = -1 + def peek(self): + i = self.index + 1 + if i < len(self.string): + return self.string[i] + else: + return None + def next(self): + self.index += 1 + if self.index < len(self.string): + return self.string[self.index] + else: + raise StopIteration + def all(self): + return self.string + +class WriteException(Exception): + pass + +class ReadException(Exception): + pass + +class JsonReader(object): + hex_digits = {'A': 10,'B': 11,'C': 12,'D': 13,'E': 14,'F':15} + escapes = {'t':'\t','n':'\n','f':'\f','r':'\r','b':'\b'} + + def read(self, s): + self._generator = _StringGenerator(s) + result = self._read() + return result + + def _read(self): + self._eatWhitespace() + peek = self._peek() + if peek is None: + raise ReadException, "Nothing to read: '%s'" % self._generator.all() + if peek == '{': + return self._readObject() + elif peek == '[': + return self._readArray() + elif peek == '"': + return self._readString() + elif peek == '-' or peek.isdigit(): + return self._readNumber() + elif peek == 't': + return self._readTrue() + elif peek == 'f': + return self._readFalse() + elif peek == 'n': + return self._readNull() + elif peek == '/': + self._readComment() + return self._read() + else: + raise ReadException, "Input is not valid JSON: '%s'" % self._generator.all() + + def _readTrue(self): + self._assertNext('t', "true") + self._assertNext('r', "true") + self._assertNext('u', "true") + self._assertNext('e', "true") + return True + + def _readFalse(self): + self._assertNext('f', "false") + self._assertNext('a', "false") + self._assertNext('l', "false") + self._assertNext('s', "false") + self._assertNext('e', "false") + return False + + def _readNull(self): + self._assertNext('n', "null") + self._assertNext('u', "null") + self._assertNext('l', "null") + self._assertNext('l', "null") + return None + + def _assertNext(self, ch, target): + if self._next() != ch: + raise ReadException, "Trying to read %s: '%s'" % (target, self._generator.all()) + + def _readNumber(self): + isfloat = False + result = self._next() + peek = self._peek() + while peek is not None and (peek.isdigit() or peek == "."): + isfloat = isfloat or peek == "." + result = result + self._next() + peek = self._peek() + try: + if isfloat: + return float(result) + else: + return int(result) + except ValueError: + raise ReadException, "Not a valid JSON number: '%s'" % result + + def _readString(self): + result = "" + assert self._next() == '"' + try: + while self._peek() != '"': + ch = self._next() + if ch == "\\": + ch = self._next() + if ch in 'brnft': + ch = self.escapes[ch] + elif ch == "u": + ch4096 = self._next() + ch256 = self._next() + ch16 = self._next() + ch1 = self._next() + n = 4096 * self._hexDigitToInt(ch4096) + n += 256 * self._hexDigitToInt(ch256) + n += 16 * self._hexDigitToInt(ch16) + n += self._hexDigitToInt(ch1) + ch = unichr(n) + elif ch not in '"/\\': + raise ReadException, "Not a valid escaped JSON character: '%s' in %s" % (ch, self._generator.all()) + result = result + ch + except StopIteration: + raise ReadException, "Not a valid JSON string: '%s'" % self._generator.all() + assert self._next() == '"' + return result + + def _hexDigitToInt(self, ch): + try: + result = self.hex_digits[ch.upper()] + except KeyError: + try: + result = int(ch) + except ValueError: + raise ReadException, "The character %s is not a hex digit." % ch + return result + + def _readComment(self): + assert self._next() == "/" + second = self._next() + if second == "/": + self._readDoubleSolidusComment() + elif second == '*': + self._readCStyleComment() + else: + raise ReadException, "Not a valid JSON comment: %s" % self._generator.all() + + def _readCStyleComment(self): + try: + done = False + while not done: + ch = self._next() + done = (ch == "*" and self._peek() == "/") + if not done and ch == "/" and self._peek() == "*": + raise ReadException, "Not a valid JSON comment: %s, '/*' cannot be embedded in the comment." % self._generator.all() + self._next() + except StopIteration: + raise ReadException, "Not a valid JSON comment: %s, expected */" % self._generator.all() + + def _readDoubleSolidusComment(self): + try: + ch = self._next() + while ch != "\r" and ch != "\n": + ch = self._next() + except StopIteration: + pass + + def _readArray(self): + result = [] + assert self._next() == '[' + done = self._peek() == ']' + while not done: + item = self._read() + result.append(item) + self._eatWhitespace() + done = self._peek() == ']' + if not done: + ch = self._next() + if ch != ",": + raise ReadException, "Not a valid JSON array: '%s' due to: '%s'" % (self._generator.all(), ch) + assert ']' == self._next() + return result + + def _readObject(self): + result = {} + assert self._next() == '{' + done = self._peek() == '}' + while not done: + key = self._read() + if type(key) is not types.StringType: + raise ReadException, "Not a valid JSON object key (should be a string): %s" % key + self._eatWhitespace() + ch = self._next() + if ch != ":": + raise ReadException, "Not a valid JSON object: '%s' due to: '%s'" % (self._generator.all(), ch) + self._eatWhitespace() + val = self._read() + result[key] = val + self._eatWhitespace() + done = self._peek() == '}' + if not done: + ch = self._next() + if ch != ",": + raise ReadException, "Not a valid JSON array: '%s' due to: '%s'" % (self._generator.all(), ch) + assert self._next() == "}" + return result + + def _eatWhitespace(self): + p = self._peek() + while p is not None and p in string.whitespace or p == '/': + if p == '/': + self._readComment() + else: + self._next() + p = self._peek() + + def _peek(self): + return self._generator.peek() + + def _next(self): + return self._generator.next() + +class JsonWriter(object): + + def _append(self, s): + self._results.append(s) + + def write(self, obj, escaped_forward_slash=False): + self._escaped_forward_slash = escaped_forward_slash + self._results = [] + self._write(obj) + return "".join(self._results) + + def _write(self, obj): + ty = type(obj) + if ty is types.DictType: + n = len(obj) + self._append("{") + for k, v in obj.items(): + self._write(k) + self._append(":") + self._write(v) + n = n - 1 + if n > 0: + self._append(",") + self._append("}") + elif ty is types.ListType or ty is types.TupleType: + n = len(obj) + self._append("[") + for item in obj: + self._write(item) + n = n - 1 + if n > 0: + self._append(",") + self._append("]") + elif ty is types.StringType or ty is types.UnicodeType: + self._append('"') + obj = obj.replace('\\', r'\\') + if self._escaped_forward_slash: + obj = obj.replace('/', r'\/') + obj = obj.replace('"', r'\"') + obj = obj.replace('\b', r'\b') + obj = obj.replace('\f', r'\f') + obj = obj.replace('\n', r'\n') + obj = obj.replace('\r', r'\r') + obj = obj.replace('\t', r'\t') + self._append(obj) + self._append('"') + elif ty is types.IntType or ty is types.LongType: + self._append(str(obj)) + elif ty is types.FloatType: + self._append("%f" % obj) + elif obj is True: + self._append("true") + elif obj is False: + self._append("false") + elif obj is None: + self._append("null") + else: + raise WriteException, "Cannot write in JSON: %s" % repr(obj) + +def write(obj, escaped_forward_slash=False): + return JsonWriter().write(obj, escaped_forward_slash) + +def read(s): + return JsonReader().read(s) diff --git a/deluge/ui/webui/lib/newforms_plus.py b/deluge/ui/webui/lib/newforms_plus.py new file mode 100644 index 000000000..2e43448f5 --- /dev/null +++ b/deluge/ui/webui/lib/newforms_plus.py @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) Martijn Voncken 2008 +# Django Licence, see ./newforms_portable/LICENCE +# + +from newforms_portable import * +import newforms_portable as newforms +from newforms_portable.forms import BoundField +from newforms_portable.util import ErrorList, escape + + +import sys, os + +import web + +#Form +class FilteredForm(newforms.Form): + """ + used to enable more complex layouts. + the filter argument contains the names of the fields to render. + """ + def _html_output_filtered(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row, filter): + """ + Helper function for outputting HTML. Used by as_table(), as_ul(), as_p(). + newforms_plus: 99% c&p from newforms, added filter. + """ + top_errors = self.non_field_errors() # Errors that should be displayed above all fields. + output, hidden_fields = [], [] + for name, field in self.fields.items(): + #FilteredForm + if (filter != None) and (not name in filter): + continue + #/FilteredForm + bf = BoundField(self, field, name) + bf_errors = ErrorList([escape(error) for error in bf.errors]) # Escape and cache in local variable. + if bf.is_hidden: + if bf_errors: + top_errors.extend(['(Hidden field %s) %s' % (name, e) for e in bf_errors]) + hidden_fields.append(unicode(bf)) + else: + if errors_on_separate_row and bf_errors: + output.append(error_row % bf_errors) + label = bf.label and bf.label_tag(escape(bf.label + ':')) or '' + if field.help_text: + help_text = help_text_html % field.help_text + else: + help_text = u'' + output.append(normal_row % {'errors': bf_errors, 'label': label, 'field': unicode(bf), 'help_text': help_text}) + if top_errors: + output.insert(0, error_row % top_errors) + if hidden_fields: # Insert any hidden fields in the last row. + str_hidden = u''.join(hidden_fields) + if output: + last_row = output[-1] + # Chop off the trailing row_ender (e.g. '') and insert the hidden fields. + output[-1] = last_row[:-len(row_ender)] + str_hidden + row_ender + else: # If there aren't any rows in the output, just append the hidden fields. + output.append(str_hidden) + return u'\n'.join(output) + + def as_table(self , filter = None): #add class="newforms" + "Returns this form rendered as HTML s -- excluding the
." + return self._html_output_filtered(u'%(label)s%(errors)s%(field)s%(help_text)s', u'%s', '', u'
%s', False, filter) + + def as_ul(self, filter = None): + "Returns this form rendered as HTML
  • s -- excluding the
      ." + return self._html_output_filtered(u'
    • %(errors)s%(label)s %(field)s%(help_text)s
    • ', u'
    • %s
    • ', '', u' %s', False , filter) + + def as_p(self , filter = None): + "Returns this form rendered as HTML

      s." + return self._html_output_filtered(u'

      %(label)s %(field)s%(help_text)s

      ', u'

      %s

      ', '

      ', u' %s', True, filter) + +class Form(FilteredForm): + info = "" + title = "No Title" + + def __init__(self,data = None): + if data == None: + data = self.initial_data() + newforms.Form.__init__(self,data) + + def initial_data(self): + "override in subclass" + return None + + def start_save(self): + "called by config_page" + data = web.Storage(self.cleaned_data) + self.validate(data) + self.save(data) + self.post_save() + + def save(self, vars): + "override in subclass" + raise NotImplementedError() + + def post_save(self): + pass + + def validate(self, data): + pass + + def pre_html(self): + return '' + + def post_html(self): + return '' + + +#convenience Input Fields. +class CheckBox(newforms.BooleanField): + "Non Required BooleanField,why the f is it required by default?" + def __init__(self,label, **kwargs): + newforms.BooleanField.__init__(self,label=label,required=False,**kwargs) + +class IntChoiceField(newforms.ChoiceField): + """same as ChoiceField, but returns an int + hint : Use IntChoiceField(choices=enumerate("list","of","strings"])) + for index-based values on a list of strings. + """ + def __init__(self, label, choices, **kwargs): + newforms.ChoiceField.__init__(self, label=label, choices=choices,**kwargs) + + def clean(self, value): + return int(newforms.ChoiceField.clean(self, value)) + +class ServerFolder(newforms.CharField): + def __init__(self, label, **kwargs): + newforms.CharField.__init__(self, label=label,**kwargs) + + def clean(self, value): + if value == None: + value = "" + value = value.rstrip('/').rstrip('\\') + self.validate(value) + return newforms.CharField.clean(self, value) + + def validate(self, value): + if (value and not os.path.isdir(value)): + raise newforms.ValidationError(_("This folder does not exist.")) + +class Password(newforms.CharField): + def __init__(self, label, **kwargs): + newforms.CharField.__init__(self, label=label, widget=newforms.PasswordInput, + **kwargs) + +#Lazy multiple select: +class _LazyCheckboxSelectMultiple(newforms.CheckboxSelectMultiple): + """ + choices are not know at define-time + choices_getter returns self.choices. + """ + def __init__(self, attrs=None,choices_getter = None): + self.choices_getter = choices_getter + newforms.CheckboxSelectMultiple.__init__(self,attrs) + + def render(self, name, value, attrs=None, choices=()): + self.choices = self.choices_getter() + return newforms.CheckboxSelectMultiple.render(self, name, value, attrs, choices) + + +class LazyMultipleChoice(newforms.MultipleChoiceField): + """ + choices are not know at define-time + choices_getter returns self.choices. + defaults to non-required. + """ + def __init__(self, label = "",widget=_LazyCheckboxSelectMultiple, + choices_getter = None, **kwargs): + + self.choices_getter = choices_getter + #default to non-required + if not 'required' in kwargs: + kwargs['required'] = False + #init, and pass get_choices to the widget. + newforms.MultipleChoiceField.__init__(self, label=label, + widget=widget(choices_getter=choices_getter),**kwargs) + + def clean(self, value): + self.choices = self.choices_getter() + return newforms.MultipleChoiceField.clean(self, value) + +#Deluge specific: +class _DelugeIntInputWidget(newforms.TextInput): + """ + because deluge-floats are edited as ints. + """ + def render(self, name, value, attrs=None): + try: + value = int(float(value)) + if value == -1 or value == None: + value = _("Unlimited") + except: + pass + return newforms.TextInput.render(self, name, value, attrs) + +class DelugeInt(newforms.IntegerField): + def __init__(self, label , **kwargs): + newforms.IntegerField.__init__(self, label=label, min_value=-1, + max_value=sys.maxint, widget=_DelugeIntInputWidget, **kwargs) + + def clean(self, value): + if str(value).lower() == _('Unlimited').lower(): + value = -1 + return int(newforms.IntegerField.clean(self, value)) + +class DelugeFloat(DelugeInt): + def clean(self, value): + try: + value = int(float(value)) #float->int + except: + pass + return float(DelugeInt.clean(self, value)) + +#/fields + + + + + diff --git a/deluge/ui/webui/lib/newforms_portable/LICENSE b/deluge/ui/webui/lib/newforms_portable/LICENSE new file mode 100644 index 000000000..ba3e68a06 --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2005, the Lawrence Journal-World +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. 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. + + 3. Neither the name of Django 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. \ No newline at end of file diff --git a/deluge/ui/webui/lib/newforms_portable/__init__.py b/deluge/ui/webui/lib/newforms_portable/__init__.py new file mode 100644 index 000000000..a34f46c8e --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/__init__.py @@ -0,0 +1,18 @@ +""" +Django validation and HTML form handling. + +TODO: + Default value for field + Field labels + Nestable Forms + FatalValidationError -- short-circuits all other validators on a form + ValidationWarning + "This form field requires foo.js" and form.js_includes() +""" + +from util import ValidationError +from widgets import * +from fields import * +from forms import * +from models import * +import django diff --git a/deluge/ui/webui/lib/newforms_portable/about.txt b/deluge/ui/webui/lib/newforms_portable/about.txt new file mode 100644 index 000000000..333869ab8 --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/about.txt @@ -0,0 +1,3 @@ +based on django rev.7350 +,/django/ contains the parts of django required to run newforms. + diff --git a/deluge/ui/webui/lib/newforms_portable/django/__init__.py b/deluge/ui/webui/lib/newforms_portable/django/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/deluge/ui/webui/lib/newforms_portable/django/core/__init__.py b/deluge/ui/webui/lib/newforms_portable/django/core/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/deluge/ui/webui/lib/newforms_portable/django/core/exceptions.py b/deluge/ui/webui/lib/newforms_portable/django/core/exceptions.py new file mode 100644 index 000000000..d9fc326cf --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/django/core/exceptions.py @@ -0,0 +1,29 @@ +"Global Django exceptions" + +class ObjectDoesNotExist(Exception): + "The requested object does not exist" + silent_variable_failure = True + +class MultipleObjectsReturned(Exception): + "The query returned multiple objects when only one was expected." + pass + +class SuspiciousOperation(Exception): + "The user did something suspicious" + pass + +class PermissionDenied(Exception): + "The user did not have permission to do that" + pass + +class ViewDoesNotExist(Exception): + "The requested view does not exist" + pass + +class MiddlewareNotUsed(Exception): + "This middleware is not used in this server configuration" + pass + +class ImproperlyConfigured(Exception): + "Django is somehow improperly configured" + pass diff --git a/deluge/ui/webui/lib/newforms_portable/django/utils/__init__.py b/deluge/ui/webui/lib/newforms_portable/django/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/deluge/ui/webui/lib/newforms_portable/django/utils/datastructures.py b/deluge/ui/webui/lib/newforms_portable/django/utils/datastructures.py new file mode 100644 index 000000000..4c278c0d8 --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/django/utils/datastructures.py @@ -0,0 +1,345 @@ +class MergeDict(object): + """ + A simple class for creating new "virtual" dictionaries that actually look + up values in more than one dictionary, passed in the constructor. + + If a key appears in more than one of the given dictionaries, only the + first occurrence will be used. + """ + def __init__(self, *dicts): + self.dicts = dicts + + def __getitem__(self, key): + for dict_ in self.dicts: + try: + return dict_[key] + except KeyError: + pass + raise KeyError + + def __copy__(self): + return self.__class__(*self.dicts) + + def get(self, key, default=None): + try: + return self[key] + except KeyError: + return default + + def getlist(self, key): + for dict_ in self.dicts: + if key in dict_.keys(): + return dict_.getlist(key) + return [] + + def items(self): + item_list = [] + for dict_ in self.dicts: + item_list.extend(dict_.items()) + return item_list + + def has_key(self, key): + for dict_ in self.dicts: + if key in dict_: + return True + return False + + __contains__ = has_key + + def copy(self): + """Returns a copy of this object.""" + return self.__copy__() + +class SortedDict(dict): + """ + A dictionary that keeps its keys in the order in which they're inserted. + """ + def __init__(self, data=None): + if data is None: + data = {} + super(SortedDict, self).__init__(data) + if isinstance(data, dict): + self.keyOrder = data.keys() + else: + self.keyOrder = [] + for key, value in data: + if key not in self.keyOrder: + self.keyOrder.append(key) + + def __deepcopy__(self, memo): + from copy import deepcopy + return self.__class__([(key, deepcopy(value, memo)) + for key, value in self.iteritems()]) + + def __setitem__(self, key, value): + super(SortedDict, self).__setitem__(key, value) + if key not in self.keyOrder: + self.keyOrder.append(key) + + def __delitem__(self, key): + super(SortedDict, self).__delitem__(key) + self.keyOrder.remove(key) + + def __iter__(self): + for k in self.keyOrder: + yield k + + def pop(self, k, *args): + result = super(SortedDict, self).pop(k, *args) + try: + self.keyOrder.remove(k) + except ValueError: + # Key wasn't in the dictionary in the first place. No problem. + pass + return result + + def popitem(self): + result = super(SortedDict, self).popitem() + self.keyOrder.remove(result[0]) + return result + + def items(self): + return zip(self.keyOrder, self.values()) + + def iteritems(self): + for key in self.keyOrder: + yield key, super(SortedDict, self).__getitem__(key) + + def keys(self): + return self.keyOrder[:] + + def iterkeys(self): + return iter(self.keyOrder) + + def values(self): + return [super(SortedDict, self).__getitem__(k) for k in self.keyOrder] + + def itervalues(self): + for key in self.keyOrder: + yield super(SortedDict, self).__getitem__(key) + + def update(self, dict_): + for k, v in dict_.items(): + self.__setitem__(k, v) + + def setdefault(self, key, default): + if key not in self.keyOrder: + self.keyOrder.append(key) + return super(SortedDict, self).setdefault(key, default) + + def value_for_index(self, index): + """Returns the value of the item at the given zero-based index.""" + return self[self.keyOrder[index]] + + def insert(self, index, key, value): + """Inserts the key, value pair before the item with the given index.""" + if key in self.keyOrder: + n = self.keyOrder.index(key) + del self.keyOrder[n] + if n < index: + index -= 1 + self.keyOrder.insert(index, key) + super(SortedDict, self).__setitem__(key, value) + + def copy(self): + """Returns a copy of this object.""" + # This way of initializing the copy means it works for subclasses, too. + obj = self.__class__(self) + obj.keyOrder = self.keyOrder[:] + return obj + + def __repr__(self): + """ + Replaces the normal dict.__repr__ with a version that returns the keys + in their sorted order. + """ + return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()]) + + def clear(self): + super(SortedDict, self).clear() + self.keyOrder = [] + +class MultiValueDictKeyError(KeyError): + pass + +class MultiValueDict(dict): + """ + A subclass of dictionary customized to handle multiple values for the + same key. + + >>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']}) + >>> d['name'] + 'Simon' + >>> d.getlist('name') + ['Adrian', 'Simon'] + >>> d.get('lastname', 'nonexistent') + 'nonexistent' + >>> d.setlist('lastname', ['Holovaty', 'Willison']) + + This class exists to solve the irritating problem raised by cgi.parse_qs, + which returns a list for every key, even though most Web forms submit + single name-value pairs. + """ + def __init__(self, key_to_list_mapping=()): + super(MultiValueDict, self).__init__(key_to_list_mapping) + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, + super(MultiValueDict, self).__repr__()) + + def __getitem__(self, key): + """ + Returns the last data value for this key, or [] if it's an empty list; + raises KeyError if not found. + """ + try: + list_ = super(MultiValueDict, self).__getitem__(key) + except KeyError: + raise MultiValueDictKeyError, "Key %r not found in %r" % (key, self) + try: + return list_[-1] + except IndexError: + return [] + + def __setitem__(self, key, value): + super(MultiValueDict, self).__setitem__(key, [value]) + + def __copy__(self): + return self.__class__(super(MultiValueDict, self).items()) + + def __deepcopy__(self, memo=None): + import copy + if memo is None: + memo = {} + result = self.__class__() + memo[id(self)] = result + for key, value in dict.items(self): + dict.__setitem__(result, copy.deepcopy(key, memo), + copy.deepcopy(value, memo)) + return result + + def get(self, key, default=None): + """ + Returns the last data value for the passed key. If key doesn't exist + or value is an empty list, then default is returned. + """ + try: + val = self[key] + except KeyError: + return default + if val == []: + return default + return val + + def getlist(self, key): + """ + Returns the list of values for the passed key. If key doesn't exist, + then an empty list is returned. + """ + try: + return super(MultiValueDict, self).__getitem__(key) + except KeyError: + return [] + + def setlist(self, key, list_): + super(MultiValueDict, self).__setitem__(key, list_) + + def setdefault(self, key, default=None): + if key not in self: + self[key] = default + return self[key] + + def setlistdefault(self, key, default_list=()): + if key not in self: + self.setlist(key, default_list) + return self.getlist(key) + + def appendlist(self, key, value): + """Appends an item to the internal list associated with key.""" + self.setlistdefault(key, []) + super(MultiValueDict, self).__setitem__(key, self.getlist(key) + [value]) + + def items(self): + """ + Returns a list of (key, value) pairs, where value is the last item in + the list associated with the key. + """ + return [(key, self[key]) for key in self.keys()] + + def lists(self): + """Returns a list of (key, list) pairs.""" + return super(MultiValueDict, self).items() + + def values(self): + """Returns a list of the last value on every key list.""" + return [self[key] for key in self.keys()] + + def copy(self): + """Returns a copy of this object.""" + return self.__deepcopy__() + + def update(self, *args, **kwargs): + """ + update() extends rather than replaces existing key lists. + Also accepts keyword args. + """ + if len(args) > 1: + raise TypeError, "update expected at most 1 arguments, got %d" % len(args) + if args: + other_dict = args[0] + if isinstance(other_dict, MultiValueDict): + for key, value_list in other_dict.lists(): + self.setlistdefault(key, []).extend(value_list) + else: + try: + for key, value in other_dict.items(): + self.setlistdefault(key, []).append(value) + except TypeError: + raise ValueError, "MultiValueDict.update() takes either a MultiValueDict or dictionary" + for key, value in kwargs.iteritems(): + self.setlistdefault(key, []).append(value) + +class DotExpandedDict(dict): + """ + A special dictionary constructor that takes a dictionary in which the keys + may contain dots to specify inner dictionaries. It's confusing, but this + example should make sense. + + >>> d = DotExpandedDict({'person.1.firstname': ['Simon'], \ + 'person.1.lastname': ['Willison'], \ + 'person.2.firstname': ['Adrian'], \ + 'person.2.lastname': ['Holovaty']}) + >>> d + {'person': {'1': {'lastname': ['Willison'], 'firstname': ['Simon']}, '2': {'lastname': ['Holovaty'], 'firstname': ['Adrian']}}} + >>> d['person'] + {'1': {'lastname': ['Willison'], 'firstname': ['Simon']}, '2': {'lastname': ['Holovaty'], 'firstname': ['Adrian']}} + >>> d['person']['1'] + {'lastname': ['Willison'], 'firstname': ['Simon']} + + # Gotcha: Results are unpredictable if the dots are "uneven": + >>> DotExpandedDict({'c.1': 2, 'c.2': 3, 'c': 1}) + {'c': 1} + """ + def __init__(self, key_to_list_mapping): + for k, v in key_to_list_mapping.items(): + current = self + bits = k.split('.') + for bit in bits[:-1]: + current = current.setdefault(bit, {}) + # Now assign value to current position + try: + current[bits[-1]] = v + except TypeError: # Special-case if current isn't a dict. + current = {bits[-1]: v} + +class FileDict(dict): + """ + A dictionary used to hold uploaded file contents. The only special feature + here is that repr() of this object won't dump the entire contents of the + file to the output. A handy safeguard for a large file upload. + """ + def __repr__(self): + if 'content' in self: + d = dict(self, content='') + return dict.__repr__(d) + return dict.__repr__(self) diff --git a/deluge/ui/webui/lib/newforms_portable/django/utils/encoding.py b/deluge/ui/webui/lib/newforms_portable/django/utils/encoding.py new file mode 100644 index 000000000..2b5219cc6 --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/django/utils/encoding.py @@ -0,0 +1,102 @@ +import types +import urllib +import datetime + +from functional import Promise +from safestring import SafeData, mark_safe + +class DjangoUnicodeDecodeError(UnicodeDecodeError): + def __init__(self, obj, *args): + self.obj = obj + UnicodeDecodeError.__init__(self, *args) + + def __str__(self): + original = UnicodeDecodeError.__str__(self) + return '%s. You passed in %r (%s)' % (original, self.obj, + type(self.obj)) + +class StrAndUnicode(object): + """ + A class whose __str__ returns its __unicode__ as a UTF-8 bytestring. + + Useful as a mix-in. + """ + def __str__(self): + return self.__unicode__().encode('utf-8') + +def smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict'): + """ + Returns a unicode object representing 's'. Treats bytestrings using the + 'encoding' codec. + + If strings_only is True, don't convert (some) non-string-like objects. + """ + if isinstance(s, Promise): + # The input is the result of a gettext_lazy() call. + return s + return force_unicode(s, encoding, strings_only, errors) + +def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'): + """ + Similar to smart_unicode, except that lazy instances are resolved to + strings, rather than kept as lazy objects. + + If strings_only is True, don't convert (some) non-string-like objects. + """ + if strings_only and isinstance(s, (types.NoneType, int, long, datetime.datetime, datetime.date, datetime.time, float)): + return s + try: + if not isinstance(s, basestring,): + if hasattr(s, '__unicode__'): + s = unicode(s) + else: + s = unicode(str(s), encoding, errors) + elif not isinstance(s, unicode): + # Note: We use .decode() here, instead of unicode(s, encoding, + # errors), so that if s is a SafeString, it ends up being a + # SafeUnicode at the end. + s = s.decode(encoding, errors) + except UnicodeDecodeError, e: + raise DjangoUnicodeDecodeError(s, *e.args) + return s + +def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'): + """ + Returns a bytestring version of 's', encoded as specified in 'encoding'. + + If strings_only is True, don't convert (some) non-string-like objects. + """ + if strings_only and isinstance(s, (types.NoneType, int)): + return s + if isinstance(s, Promise): + return unicode(s).encode(encoding, errors) + elif not isinstance(s, basestring): + try: + return str(s) + except UnicodeEncodeError: + return unicode(s).encode(encoding, errors) + elif isinstance(s, unicode): + return s.encode(encoding, errors) + elif s and encoding != 'utf-8': + return s.decode('utf-8', errors).encode(encoding, errors) + else: + return s + +def iri_to_uri(iri): + """ + Convert an Internationalized Resource Identifier (IRI) portion to a URI + portion that is suitable for inclusion in a URL. + + This is the algorithm from section 3.1 of RFC 3987. However, since we are + assuming input is either UTF-8 or unicode already, we can simplify things a + little from the full method. + + Returns an ASCII string containing the encoded result. + """ + # The list of safe characters here is constructed from the printable ASCII + # characters that are not explicitly excluded by the list at the end of + # section 3.1 of RFC 3987. + if iri is None: + return iri + return urllib.quote(smart_str(iri), safe='/#%[]=:;$&()+,!?*') + diff --git a/deluge/ui/webui/lib/newforms_portable/django/utils/functional.py b/deluge/ui/webui/lib/newforms_portable/django/utils/functional.py new file mode 100644 index 000000000..3de693e18 --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/django/utils/functional.py @@ -0,0 +1,241 @@ +# License for code in this file that was taken from Python 2.5. + +# PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +# -------------------------------------------- +# +# 1. This LICENSE AGREEMENT is between the Python Software Foundation +# ("PSF"), and the Individual or Organization ("Licensee") accessing and +# otherwise using this software ("Python") in source or binary form and +# its associated documentation. +# +# 2. Subject to the terms and conditions of this License Agreement, PSF +# hereby grants Licensee a nonexclusive, royalty-free, world-wide +# license to reproduce, analyze, test, perform and/or display publicly, +# prepare derivative works, distribute, and otherwise use Python +# alone or in any derivative version, provided, however, that PSF's +# License Agreement and PSF's notice of copyright, i.e., "Copyright (c) +# 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation; +# All Rights Reserved" are retained in Python alone or in any derivative +# version prepared by Licensee. +# +# 3. In the event Licensee prepares a derivative work that is based on +# or incorporates Python or any part thereof, and wants to make +# the derivative work available to others as provided herein, then +# Licensee hereby agrees to include in any such work a brief summary of +# the changes made to Python. +# +# 4. PSF is making Python available to Licensee on an "AS IS" +# basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +# IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +# DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +# FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +# INFRINGE ANY THIRD PARTY RIGHTS. +# +# 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +# FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +# A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +# OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. +# +# 6. This License Agreement will automatically terminate upon a material +# breach of its terms and conditions. +# +# 7. Nothing in this License Agreement shall be deemed to create any +# relationship of agency, partnership, or joint venture between PSF and +# Licensee. This License Agreement does not grant permission to use PSF +# trademarks or trade name in a trademark sense to endorse or promote +# products or services of Licensee, or any third party. +# +# 8. By copying, installing or otherwise using Python, Licensee +# agrees to be bound by the terms and conditions of this License +# Agreement. + + +def curry(_curried_func, *args, **kwargs): + def _curried(*moreargs, **morekwargs): + return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs)) + return _curried + +### Begin from Python 2.5 functools.py ######################################## + +# Summary of changes made to the Python 2.5 code below: +# * swapped ``partial`` for ``curry`` to maintain backwards-compatibility +# in Django. +# * Wrapped the ``setattr`` call in ``update_wrapper`` with a try-except +# block to make it compatible with Python 2.3, which doesn't allow +# assigning to ``__name__``. + +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation. +# All Rights Reserved. + +############################################################################### + +# update_wrapper() and wraps() are tools to help write +# wrapper functions that can handle naive introspection + +WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__') +WRAPPER_UPDATES = ('__dict__',) +def update_wrapper(wrapper, + wrapped, + assigned = WRAPPER_ASSIGNMENTS, + updated = WRAPPER_UPDATES): + """Update a wrapper function to look like the wrapped function + + wrapper is the function to be updated + wrapped is the original function + assigned is a tuple naming the attributes assigned directly + from the wrapped function to the wrapper function (defaults to + functools.WRAPPER_ASSIGNMENTS) + updated is a tuple naming the attributes off the wrapper that + are updated with the corresponding attribute from the wrapped + function (defaults to functools.WRAPPER_UPDATES) + """ + for attr in assigned: + try: + setattr(wrapper, attr, getattr(wrapped, attr)) + except TypeError: # Python 2.3 doesn't allow assigning to __name__. + pass + for attr in updated: + getattr(wrapper, attr).update(getattr(wrapped, attr)) + # Return the wrapper so this can be used as a decorator via curry() + return wrapper + +def wraps(wrapped, + assigned = WRAPPER_ASSIGNMENTS, + updated = WRAPPER_UPDATES): + """Decorator factory to apply update_wrapper() to a wrapper function + + Returns a decorator that invokes update_wrapper() with the decorated + function as the wrapper argument and the arguments to wraps() as the + remaining arguments. Default arguments are as for update_wrapper(). + This is a convenience function to simplify applying curry() to + update_wrapper(). + """ + return curry(update_wrapper, wrapped=wrapped, + assigned=assigned, updated=updated) + +### End from Python 2.5 functools.py ########################################## + +def memoize(func, cache, num_args): + """ + Wrap a function so that results for any argument tuple are stored in + 'cache'. Note that the args to the function must be usable as dictionary + keys. + + Only the first num_args are considered when creating the key. + """ + def wrapper(*args): + mem_args = args[:num_args] + if mem_args in cache: + return cache[mem_args] + result = func(*args) + cache[mem_args] = result + return result + return wraps(func)(wrapper) + +class Promise(object): + """ + This is just a base class for the proxy class created in + the closure of the lazy function. It can be used to recognize + promises in code. + """ + pass + +def lazy(func, *resultclasses): + """ + Turns any callable into a lazy evaluated callable. You need to give result + classes or types -- at least one is needed so that the automatic forcing of + the lazy evaluation code is triggered. Results are not memoized; the + function is evaluated on every access. + """ + class __proxy__(Promise): + # This inner class encapsulates the code that should be evaluated + # lazily. On calling of one of the magic methods it will force + # the evaluation and store the result. Afterwards, the result + # is delivered directly. So the result is memoized. + def __init__(self, args, kw): + self.__func = func + self.__args = args + self.__kw = kw + self.__dispatch = {} + for resultclass in resultclasses: + self.__dispatch[resultclass] = {} + for (k, v) in resultclass.__dict__.items(): + setattr(self, k, self.__promise__(resultclass, k, v)) + self._delegate_str = str in resultclasses + self._delegate_unicode = unicode in resultclasses + assert not (self._delegate_str and self._delegate_unicode), "Cannot call lazy() with both str and unicode return types." + if self._delegate_unicode: + # Each call to lazy() makes a new __proxy__ object, so this + # doesn't interfere with any other lazy() results. + __proxy__.__unicode__ = __proxy__.__unicode_cast + elif self._delegate_str: + __proxy__.__str__ = __proxy__.__str_cast + + def __promise__(self, klass, funcname, func): + # Builds a wrapper around some magic method and registers that magic + # method for the given type and method name. + def __wrapper__(*args, **kw): + # Automatically triggers the evaluation of a lazy value and + # applies the given magic method of the result type. + res = self.__func(*self.__args, **self.__kw) + return self.__dispatch[type(res)][funcname](res, *args, **kw) + + if klass not in self.__dispatch: + self.__dispatch[klass] = {} + self.__dispatch[klass][funcname] = func + return __wrapper__ + + def __unicode_cast(self): + return self.__func(*self.__args, **self.__kw) + + def __str_cast(self): + return str(self.__func(*self.__args, **self.__kw)) + + def __cmp__(self, rhs): + if self._delegate_str: + s = str(self.__func(*self.__args, **self.__kw)) + elif self._delegate_unicode: + s = unicode(self.__func(*self.__args, **self.__kw)) + else: + s = self.__func(*self.__args, **self.__kw) + if isinstance(rhs, Promise): + return -cmp(rhs, s) + else: + return cmp(s, rhs) + + def __mod__(self, rhs): + if self._delegate_str: + return str(self) % rhs + elif self._delegate_unicode: + return unicode(self) % rhs + else: + raise AssertionError('__mod__ not supported for non-string types') + + def __deepcopy__(self, memo): + # Instances of this class are effectively immutable. It's just a + # collection of functions. So we don't need to do anything + # complicated for copying. + memo[id(self)] = self + return self + + def __wrapper__(*args, **kw): + # Creates the proxy object, instead of the actual value. + return __proxy__(args, kw) + + return wraps(func)(__wrapper__) + +def allow_lazy(func, *resultclasses): + """ + A decorator that allows a function to be called with one or more lazy + arguments. If none of the args are lazy, the function is evaluated + immediately, otherwise a __proxy__ is returned that will evaluate the + function when needed. + """ + def wrapper(*args, **kwargs): + for arg in list(args) + kwargs.values(): + if isinstance(arg, Promise): + break + else: + return func(*args, **kwargs) + return lazy(func, *resultclasses)(*args, **kwargs) + return wraps(func)(wrapper) diff --git a/deluge/ui/webui/lib/newforms_portable/django/utils/html.py b/deluge/ui/webui/lib/newforms_portable/django/utils/html.py new file mode 100644 index 000000000..3ac39864d --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/django/utils/html.py @@ -0,0 +1,163 @@ +"""HTML utilities suitable for global use.""" + +import re +import string + +from safestring import SafeData, mark_safe +from encoding import force_unicode +from functional import allow_lazy +from http import urlquote + +# Configuration for urlize() function. +LEADING_PUNCTUATION = ['(', '<', '<'] +TRAILING_PUNCTUATION = ['.', ',', ')', '>', '\n', '>'] + +# List of possible strings used for bullets in bulleted lists. +DOTS = ['·', '*', '\xe2\x80\xa2', '•', '•', '•'] + +unencoded_ampersands_re = re.compile(r'&(?!(\w+|#\d+);)') +word_split_re = re.compile(r'(\s+)') +punctuation_re = re.compile('^(?P(?:%s)*)(?P.*?)(?P(?:%s)*)$' % \ + ('|'.join([re.escape(x) for x in LEADING_PUNCTUATION]), + '|'.join([re.escape(x) for x in TRAILING_PUNCTUATION]))) +simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$') +link_target_attribute_re = re.compile(r'(]*?)target=[^\s>]+') +html_gunk_re = re.compile(r'(?:
      |<\/i>|<\/b>|<\/em>|<\/strong>|<\/?smallcaps>|<\/?uppercase>)', re.IGNORECASE) +hard_coded_bullets_re = re.compile(r'((?:

      (?:%s).*?[a-zA-Z].*?

      \s*)+)' % '|'.join([re.escape(x) for x in DOTS]), re.DOTALL) +trailing_empty_content_re = re.compile(r'(?:

      (?: |\s|
      )*?

      \s*)+\Z') +del x # Temporary variable + +def escape(html): + """Returns the given HTML with ampersands, quotes and carets encoded.""" + return mark_safe(force_unicode(html).replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"').replace("'", ''')) +escape = allow_lazy(escape, unicode) + +def conditional_escape(html): + """ + Similar to escape(), except that it doesn't operate on pre-escaped strings. + """ + if isinstance(html, SafeData): + return html + else: + return escape(html) + +def linebreaks(value, autoescape=False): + """Converts newlines into

      and
      s.""" + value = re.sub(r'\r\n|\r|\n', '\n', force_unicode(value)) # normalize newlines + paras = re.split('\n{2,}', value) + if autoescape: + paras = [u'

      %s

      ' % escape(p.strip()).replace('\n', '
      ') for p in paras] + else: + paras = [u'

      %s

      ' % p.strip().replace('\n', '
      ') for p in paras] + return u'\n\n'.join(paras) +linebreaks = allow_lazy(linebreaks, unicode) + +def strip_tags(value): + """Returns the given HTML with all tags stripped.""" + return re.sub(r'<[^>]*?>', '', force_unicode(value)) +strip_tags = allow_lazy(strip_tags) + +def strip_spaces_between_tags(value): + """Returns the given HTML with spaces between tags removed.""" + return re.sub(r'>\s+<', '><', force_unicode(value)) +strip_spaces_between_tags = allow_lazy(strip_spaces_between_tags, unicode) + +def strip_entities(value): + """Returns the given HTML with all entities (&something;) stripped.""" + return re.sub(r'&(?:\w+|#\d+);', '', force_unicode(value)) +strip_entities = allow_lazy(strip_entities, unicode) + +def fix_ampersands(value): + """Returns the given HTML with all unencoded ampersands encoded correctly.""" + return unencoded_ampersands_re.sub('&', force_unicode(value)) +fix_ampersands = allow_lazy(fix_ampersands, unicode) + +def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False): + """ + Converts any URLs in text into clickable links. + + Works on http://, https://, and www. links. Links can have trailing + punctuation (periods, commas, close-parens) and leading punctuation + (opening parens) and it'll still do the right thing. + + If trim_url_limit is not None, the URLs in link text longer than this limit + will truncated to trim_url_limit-3 characters and appended with an elipsis. + + If nofollow is True, the URLs in link text will get a rel="nofollow" + attribute. + """ + if autoescape: + trim_url = lambda x, limit=trim_url_limit: conditional_escape(limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x) + else: + trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x + safe_input = isinstance(text, SafeData) + words = word_split_re.split(force_unicode(text)) + nofollow_attr = nofollow and ' rel="nofollow"' or '' + for i, word in enumerate(words): + match = punctuation_re.match(word) + if match: + lead, middle, trail = match.groups() + if safe_input: + middle = mark_safe(middle) + if middle.startswith('www.') or ('@' not in middle and not middle.startswith('http://') and \ + len(middle) > 0 and middle[0] in string.ascii_letters + string.digits and \ + (middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))): + middle = 'http://%s' % middle + if middle.startswith('http://') or middle.startswith('https://'): + url = urlquote(middle, safe='/&=:;#?+*') + if autoescape and not safe_input: + url = escape(url) + trimmed_url = trim_url(middle) + middle = '
      %s' % (url, nofollow_attr, + trimmed_url) + elif '@' in middle and not middle.startswith('www.') and \ + not ':' in middle and simple_email_re.match(middle): + if autoescape: + middle = conditional_escape(middle) + middle = '%s' % (middle, middle) + if lead + middle + trail != word: + if autoescape and not safe_input: + lead, trail = escape(lead), escape(trail) + words[i] = mark_safe('%s%s%s' % (lead, middle, trail)) + elif autoescape and not safe_input: + words[i] = escape(word) + elif safe_input: + words[i] = mark_safe(word) + elif autoescape: + words[i] = escape(word) + return u''.join(words) +urlize = allow_lazy(urlize, unicode) + +def clean_html(text): + """ + Clean the given HTML. Specifically, do the following: + * Convert and to and . + * Encode all ampersands correctly. + * Remove all "target" attributes from tags. + * Remove extraneous HTML, such as presentational tags that open and + immediately close and
      . + * Convert hard-coded bullets into HTML unordered lists. + * Remove stuff like "

        

      ", but only if it's at the + bottom of the text. + """ + from django.utils.text import normalize_newlines + text = normalize_newlines(force_unicode(text)) + text = re.sub(r'<(/?)\s*b\s*>', '<\\1strong>', text) + text = re.sub(r'<(/?)\s*i\s*>', '<\\1em>', text) + text = fix_ampersands(text) + # Remove all target="" attributes from
      tags. + text = link_target_attribute_re.sub('\\1', text) + # Trim stupid HTML such as
      . + text = html_gunk_re.sub('', text) + # Convert hard-coded bullets into HTML unordered lists. + def replace_p_tags(match): + s = match.group().replace('

      ', '') + for d in DOTS: + s = s.replace('

      %s' % d, '

    • ') + return u'
        \n%s\n
      ' % s + text = hard_coded_bullets_re.sub(replace_p_tags, text) + # Remove stuff like "

        

      ", but only if it's at the bottom + # of the text. + text = trailing_empty_content_re.sub('', text) + return text +clean_html = allow_lazy(clean_html, unicode) diff --git a/deluge/ui/webui/lib/newforms_portable/django/utils/http.py b/deluge/ui/webui/lib/newforms_portable/django/utils/http.py new file mode 100644 index 000000000..db8bb9644 --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/django/utils/http.py @@ -0,0 +1,67 @@ +import urllib +from email.Utils import formatdate + +from encoding import smart_str, force_unicode +from functional import allow_lazy + +def urlquote(url, safe='/'): + """ + A version of Python's urllib.quote() function that can operate on unicode + strings. The url is first UTF-8 encoded before quoting. The returned string + can safely be used as part of an argument to a subsequent iri_to_uri() call + without double-quoting occurring. + """ + return force_unicode(urllib.quote(smart_str(url), safe)) + +urlquote = allow_lazy(urlquote, unicode) + +def urlquote_plus(url, safe=''): + """ + A version of Python's urllib.quote_plus() function that can operate on + unicode strings. The url is first UTF-8 encoded before quoting. The + returned string can safely be used as part of an argument to a subsequent + iri_to_uri() call without double-quoting occurring. + """ + return force_unicode(urllib.quote_plus(smart_str(url), safe)) +urlquote_plus = allow_lazy(urlquote_plus, unicode) + +def urlencode(query, doseq=0): + """ + A version of Python's urllib.urlencode() function that can operate on + unicode strings. The parameters are first case to UTF-8 encoded strings and + then encoded as per normal. + """ + if hasattr(query, 'items'): + query = query.items() + return urllib.urlencode( + [(smart_str(k), + isinstance(v, (list,tuple)) and [smart_str(i) for i in v] or smart_str(v)) + for k, v in query], + doseq) + +def cookie_date(epoch_seconds=None): + """ + Formats the time to ensure compatibility with Netscape's cookie standard. + + Accepts a floating point number expressed in seconds since the epoch, in + UTC - such as that outputted by time.time(). If set to None, defaults to + the current time. + + Outputs a string in the format 'Wdy, DD-Mon-YYYY HH:MM:SS GMT'. + """ + rfcdate = formatdate(epoch_seconds) + return '%s-%s-%s GMT' % (rfcdate[:7], rfcdate[8:11], rfcdate[12:25]) + +def http_date(epoch_seconds=None): + """ + Formats the time to match the RFC1123 date format as specified by HTTP + RFC2616 section 3.3.1. + + Accepts a floating point number expressed in seconds since the epoch, in + UTC - such as that outputted by time.time(). If set to None, defaults to + the current time. + + Outputs a string in the format 'Wdy, DD Mon YYYY HH:MM:SS GMT'. + """ + rfcdate = formatdate(epoch_seconds) + return '%s GMT' % rfcdate[:25] diff --git a/deluge/ui/webui/lib/newforms_portable/django/utils/safestring.py b/deluge/ui/webui/lib/newforms_portable/django/utils/safestring.py new file mode 100644 index 000000000..99658fb8b --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/django/utils/safestring.py @@ -0,0 +1,119 @@ +""" +Functions for working with "safe strings": strings that can be displayed safely +without further escaping in HTML. Marking something as a "safe string" means +that the producer of the string has already turned characters that should not +be interpreted by the HTML engine (e.g. '<') into the appropriate entities. +""" +from functional import curry, Promise + +class EscapeData(object): + pass + +class EscapeString(str, EscapeData): + """ + A string that should be HTML-escaped when output. + """ + pass + +class EscapeUnicode(unicode, EscapeData): + """ + A unicode object that should be HTML-escaped when output. + """ + pass + +class SafeData(object): + pass + +class SafeString(str, SafeData): + """ + A string subclass that has been specifically marked as "safe" (requires no + further escaping) for HTML output purposes. + """ + def __add__(self, rhs): + """ + Concatenating a safe string with another safe string or safe unicode + object is safe. Otherwise, the result is no longer safe. + """ + t = super(SafeString, self).__add__(rhs) + if isinstance(rhs, SafeUnicode): + return SafeUnicode(t) + elif isinstance(rhs, SafeString): + return SafeString(t) + return t + + def _proxy_method(self, *args, **kwargs): + """ + Wrap a call to a normal unicode method up so that we return safe + results. The method that is being wrapped is passed in the 'method' + argument. + """ + method = kwargs.pop('method') + data = method(self, *args, **kwargs) + if isinstance(data, str): + return SafeString(data) + else: + return SafeUnicode(data) + + decode = curry(_proxy_method, method = str.decode) + +class SafeUnicode(unicode, SafeData): + """ + A unicode subclass that has been specifically marked as "safe" for HTML + output purposes. + """ + def __add__(self, rhs): + """ + Concatenating a safe unicode object with another safe string or safe + unicode object is safe. Otherwise, the result is no longer safe. + """ + t = super(SafeUnicode, self).__add__(rhs) + if isinstance(rhs, SafeData): + return SafeUnicode(t) + return t + + def _proxy_method(self, *args, **kwargs): + """ + Wrap a call to a normal unicode method up so that we return safe + results. The method that is being wrapped is passed in the 'method' + argument. + """ + method = kwargs.pop('method') + data = method(self, *args, **kwargs) + if isinstance(data, str): + return SafeString(data) + else: + return SafeUnicode(data) + + encode = curry(_proxy_method, method = unicode.encode) + +def mark_safe(s): + """ + Explicitly mark a string as safe for (HTML) output purposes. The returned + object can be used everywhere a string or unicode object is appropriate. + + Can be called multiple times on a single string. + """ + if isinstance(s, SafeData): + return s + if isinstance(s, str) or (isinstance(s, Promise) and s._delegate_str): + return SafeString(s) + if isinstance(s, (unicode, Promise)): + return SafeUnicode(s) + return SafeString(str(s)) + +def mark_for_escaping(s): + """ + Explicitly mark a string as requiring HTML escaping upon output. Has no + effect on SafeData subclasses. + + Can be called multiple times on a single string (the resulting escaping is + only applied once). + """ + if isinstance(s, (SafeData, EscapeData)): + return s + if isinstance(s, str) or (isinstance(s, Promise) and s._delegate_str): + return EscapeString(s) + if isinstance(s, (unicode, Promise)): + return EscapeUnicode(s) + return EscapeString(str(s)) + diff --git a/deluge/ui/webui/lib/newforms_portable/django/utils/translation.py b/deluge/ui/webui/lib/newforms_portable/django/utils/translation.py new file mode 100644 index 000000000..ad65bd959 --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/django/utils/translation.py @@ -0,0 +1,9 @@ +try: + _('translate something') +except: + import gettext + gettext.install('locale') + +ugettext = _ +ugettext_lazy = _ + diff --git a/deluge/ui/webui/lib/newforms_portable/fields.py b/deluge/ui/webui/lib/newforms_portable/fields.py new file mode 100644 index 000000000..c20899ada --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/fields.py @@ -0,0 +1,784 @@ +""" +Field classes. +""" + +import copy +import datetime +import os +import re +import time +# Python 2.3 fallbacks +try: + from decimal import Decimal, DecimalException +except ImportError: + from django.utils._decimal import Decimal, DecimalException +try: + set +except NameError: + from sets import Set as set + +from django.utils.translation import ugettext_lazy as _ +from django.utils.encoding import StrAndUnicode, smart_unicode, smart_str + +from util import ErrorList, ValidationError +from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput + + +__all__ = ( + 'Field', 'CharField', 'IntegerField', + 'DEFAULT_DATE_INPUT_FORMATS', 'DateField', + 'DEFAULT_TIME_INPUT_FORMATS', 'TimeField', + 'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField', + 'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField', + 'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField', + 'ComboField', 'MultiValueField', 'FloatField', 'DecimalField', + 'SplitDateTimeField', 'IPAddressField', 'FilePathField', +) + +# These values, if given to to_python(), will trigger the self.required check. +EMPTY_VALUES = (None, '') + + +class Field(object): + widget = TextInput # Default widget to use when rendering this type of Field. + hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden". + default_error_messages = { + 'required': _(u'This field is required.'), + 'invalid': _(u'Enter a valid value.'), + } + + # Tracks each time a Field instance is created. Used to retain order. + creation_counter = 0 + + def __init__(self, required=True, widget=None, label=None, initial=None, + help_text=None, error_messages=None): + # required -- Boolean that specifies whether the field is required. + # True by default. + # widget -- A Widget class, or instance of a Widget class, that should + # be used for this Field when displaying it. Each Field has a + # default Widget that it'll use if you don't specify this. In + # most cases, the default widget is TextInput. + # label -- A verbose name for this field, for use in displaying this + # field in a form. By default, Django will use a "pretty" + # version of the form field name, if the Field is part of a + # Form. + # initial -- A value to use in this Field's initial display. This value + # is *not* used as a fallback if data isn't given. + # help_text -- An optional string to use as "help text" for this Field. + if label is not None: + label = smart_unicode(label) + self.required, self.label, self.initial = required, label, initial + self.help_text = smart_unicode(help_text or '') + widget = widget or self.widget + if isinstance(widget, type): + widget = widget() + + # Hook into self.widget_attrs() for any Field-specific HTML attributes. + extra_attrs = self.widget_attrs(widget) + if extra_attrs: + widget.attrs.update(extra_attrs) + + self.widget = widget + + # Increase the creation counter, and save our local copy. + self.creation_counter = Field.creation_counter + Field.creation_counter += 1 + + def set_class_error_messages(messages, klass): + for base_class in klass.__bases__: + set_class_error_messages(messages, base_class) + messages.update(getattr(klass, 'default_error_messages', {})) + + messages = {} + set_class_error_messages(messages, self.__class__) + messages.update(error_messages or {}) + self.error_messages = messages + + def clean(self, value): + """ + Validates the given value and returns its "cleaned" value as an + appropriate Python object. + + Raises ValidationError for any errors. + """ + if self.required and value in EMPTY_VALUES: + raise ValidationError(self.error_messages['required']) + return value + + def widget_attrs(self, widget): + """ + Given a Widget instance (*not* a Widget class), returns a dictionary of + any HTML attributes that should be added to the Widget, based on this + Field. + """ + return {} + + def __deepcopy__(self, memo): + result = copy.copy(self) + memo[id(self)] = result + result.widget = copy.deepcopy(self.widget, memo) + return result + +class CharField(Field): + default_error_messages = { + 'max_length': _(u'Ensure this value has at most %(max)d characters (it has %(length)d).'), + 'min_length': _(u'Ensure this value has at least %(min)d characters (it has %(length)d).'), + } + + def __init__(self, max_length=None, min_length=None, *args, **kwargs): + self.max_length, self.min_length = max_length, min_length + super(CharField, self).__init__(*args, **kwargs) + + def clean(self, value): + "Validates max_length and min_length. Returns a Unicode object." + super(CharField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + value = smart_unicode(value) + value_length = len(value) + if self.max_length is not None and value_length > self.max_length: + raise ValidationError(self.error_messages['max_length'] % {'max': self.max_length, 'length': value_length}) + if self.min_length is not None and value_length < self.min_length: + raise ValidationError(self.error_messages['min_length'] % {'min': self.min_length, 'length': value_length}) + return value + + def widget_attrs(self, widget): + if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)): + # The HTML attribute is maxlength, not max_length. + return {'maxlength': str(self.max_length)} + +class IntegerField(Field): + default_error_messages = { + 'invalid': _(u'Enter a whole number.'), + 'max_value': _(u'Ensure this value is less than or equal to %s.'), + 'min_value': _(u'Ensure this value is greater than or equal to %s.'), + } + + def __init__(self, max_value=None, min_value=None, *args, **kwargs): + self.max_value, self.min_value = max_value, min_value + super(IntegerField, self).__init__(*args, **kwargs) + + def clean(self, value): + """ + Validates that int() can be called on the input. Returns the result + of int(). Returns None for empty values. + """ + super(IntegerField, self).clean(value) + if value in EMPTY_VALUES: + return None + try: + value = int(str(value)) + except (ValueError, TypeError): + raise ValidationError(self.error_messages['invalid']) + if self.max_value is not None and value > self.max_value: + raise ValidationError(self.error_messages['max_value'] % self.max_value) + if self.min_value is not None and value < self.min_value: + raise ValidationError(self.error_messages['min_value'] % self.min_value) + return value + +class FloatField(Field): + default_error_messages = { + 'invalid': _(u'Enter a number.'), + 'max_value': _(u'Ensure this value is less than or equal to %s.'), + 'min_value': _(u'Ensure this value is greater than or equal to %s.'), + } + + def __init__(self, max_value=None, min_value=None, *args, **kwargs): + self.max_value, self.min_value = max_value, min_value + Field.__init__(self, *args, **kwargs) + + def clean(self, value): + """ + Validates that float() can be called on the input. Returns a float. + Returns None for empty values. + """ + super(FloatField, self).clean(value) + if not self.required and value in EMPTY_VALUES: + return None + try: + value = float(value) + except (ValueError, TypeError): + raise ValidationError(self.error_messages['invalid']) + if self.max_value is not None and value > self.max_value: + raise ValidationError(self.error_messages['max_value'] % self.max_value) + if self.min_value is not None and value < self.min_value: + raise ValidationError(self.error_messages['min_value'] % self.min_value) + return value + +class DecimalField(Field): + default_error_messages = { + 'invalid': _(u'Enter a number.'), + 'max_value': _(u'Ensure this value is less than or equal to %s.'), + 'min_value': _(u'Ensure this value is greater than or equal to %s.'), + 'max_digits': _('Ensure that there are no more than %s digits in total.'), + 'max_decimal_places': _('Ensure that there are no more than %s decimal places.'), + 'max_whole_digits': _('Ensure that there are no more than %s digits before the decimal point.') + } + + def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs): + self.max_value, self.min_value = max_value, min_value + self.max_digits, self.decimal_places = max_digits, decimal_places + Field.__init__(self, *args, **kwargs) + + def clean(self, value): + """ + Validates that the input is a decimal number. Returns a Decimal + instance. Returns None for empty values. Ensures that there are no more + than max_digits in the number, and no more than decimal_places digits + after the decimal point. + """ + super(DecimalField, self).clean(value) + if not self.required and value in EMPTY_VALUES: + return None + value = smart_str(value).strip() + try: + value = Decimal(value) + except DecimalException: + raise ValidationError(self.error_messages['invalid']) + pieces = str(value).lstrip("-").split('.') + decimals = (len(pieces) == 2) and len(pieces[1]) or 0 + digits = len(pieces[0]) + if self.max_value is not None and value > self.max_value: + raise ValidationError(self.error_messages['max_value'] % self.max_value) + if self.min_value is not None and value < self.min_value: + raise ValidationError(self.error_messages['min_value'] % self.min_value) + if self.max_digits is not None and (digits + decimals) > self.max_digits: + raise ValidationError(self.error_messages['max_digits'] % self.max_digits) + if self.decimal_places is not None and decimals > self.decimal_places: + raise ValidationError(self.error_messages['max_decimal_places'] % self.decimal_places) + if self.max_digits is not None and self.decimal_places is not None and digits > (self.max_digits - self.decimal_places): + raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places)) + return value + +DEFAULT_DATE_INPUT_FORMATS = ( + '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' + '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006' + '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006' + '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006' + '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' +) + +class DateField(Field): + default_error_messages = { + 'invalid': _(u'Enter a valid date.'), + } + + def __init__(self, input_formats=None, *args, **kwargs): + super(DateField, self).__init__(*args, **kwargs) + self.input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS + + def clean(self, value): + """ + Validates that the input can be converted to a date. Returns a Python + datetime.date object. + """ + super(DateField, self).clean(value) + if value in EMPTY_VALUES: + return None + if isinstance(value, datetime.datetime): + return value.date() + if isinstance(value, datetime.date): + return value + for format in self.input_formats: + try: + return datetime.date(*time.strptime(value, format)[:3]) + except ValueError: + continue + raise ValidationError(self.error_messages['invalid']) + +DEFAULT_TIME_INPUT_FORMATS = ( + '%H:%M:%S', # '14:30:59' + '%H:%M', # '14:30' +) + +class TimeField(Field): + default_error_messages = { + 'invalid': _(u'Enter a valid time.') + } + + def __init__(self, input_formats=None, *args, **kwargs): + super(TimeField, self).__init__(*args, **kwargs) + self.input_formats = input_formats or DEFAULT_TIME_INPUT_FORMATS + + def clean(self, value): + """ + Validates that the input can be converted to a time. Returns a Python + datetime.time object. + """ + super(TimeField, self).clean(value) + if value in EMPTY_VALUES: + return None + if isinstance(value, datetime.time): + return value + for format in self.input_formats: + try: + return datetime.time(*time.strptime(value, format)[3:6]) + except ValueError: + continue + raise ValidationError(self.error_messages['invalid']) + +DEFAULT_DATETIME_INPUT_FORMATS = ( + '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' + '%Y-%m-%d %H:%M', # '2006-10-25 14:30' + '%Y-%m-%d', # '2006-10-25' + '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59' + '%m/%d/%Y %H:%M', # '10/25/2006 14:30' + '%m/%d/%Y', # '10/25/2006' + '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59' + '%m/%d/%y %H:%M', # '10/25/06 14:30' + '%m/%d/%y', # '10/25/06' +) + +class DateTimeField(Field): + widget = DateTimeInput + default_error_messages = { + 'invalid': _(u'Enter a valid date/time.'), + } + + def __init__(self, input_formats=None, *args, **kwargs): + super(DateTimeField, self).__init__(*args, **kwargs) + self.input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS + + def clean(self, value): + """ + Validates that the input can be converted to a datetime. Returns a + Python datetime.datetime object. + """ + super(DateTimeField, self).clean(value) + if value in EMPTY_VALUES: + return None + if isinstance(value, datetime.datetime): + return value + if isinstance(value, datetime.date): + return datetime.datetime(value.year, value.month, value.day) + if isinstance(value, list): + # Input comes from a SplitDateTimeWidget, for example. So, it's two + # components: date and time. + if len(value) != 2: + raise ValidationError(self.error_messages['invalid']) + value = '%s %s' % tuple(value) + for format in self.input_formats: + try: + return datetime.datetime(*time.strptime(value, format)[:6]) + except ValueError: + continue + raise ValidationError(self.error_messages['invalid']) + +class RegexField(CharField): + def __init__(self, regex, max_length=None, min_length=None, error_message=None, *args, **kwargs): + """ + regex can be either a string or a compiled regular expression object. + error_message is an optional error message to use, if + 'Enter a valid value' is too generic for you. + """ + # error_message is just kept for backwards compatibility: + if error_message: + error_messages = kwargs.get('error_messages') or {} + error_messages['invalid'] = error_message + kwargs['error_messages'] = error_messages + super(RegexField, self).__init__(max_length, min_length, *args, **kwargs) + if isinstance(regex, basestring): + regex = re.compile(regex) + self.regex = regex + + def clean(self, value): + """ + Validates that the input matches the regular expression. Returns a + Unicode object. + """ + value = super(RegexField, self).clean(value) + if value == u'': + return value + if not self.regex.search(value): + raise ValidationError(self.error_messages['invalid']) + return value + +email_re = re.compile( + r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom + r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string + r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain + +class EmailField(RegexField): + default_error_messages = { + 'invalid': _(u'Enter a valid e-mail address.'), + } + + def __init__(self, max_length=None, min_length=None, *args, **kwargs): + RegexField.__init__(self, email_re, max_length, min_length, *args, + **kwargs) + +try: + from django.conf import settings + URL_VALIDATOR_USER_AGENT = settings.URL_VALIDATOR_USER_AGENT +except ImportError: + # It's OK if Django settings aren't configured. + URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)' + +class UploadedFile(StrAndUnicode): + "A wrapper for files uploaded in a FileField" + def __init__(self, filename, content): + self.filename = filename + self.content = content + + def __unicode__(self): + """ + The unicode representation is the filename, so that the pre-database-insertion + logic can use UploadedFile objects + """ + return self.filename + +class FileField(Field): + widget = FileInput + default_error_messages = { + 'invalid': _(u"No file was submitted. Check the encoding type on the form."), + 'missing': _(u"No file was submitted."), + 'empty': _(u"The submitted file is empty."), + } + + def __init__(self, *args, **kwargs): + super(FileField, self).__init__(*args, **kwargs) + + def clean(self, data, initial=None): + super(FileField, self).clean(initial or data) + if not self.required and data in EMPTY_VALUES: + return None + elif not data and initial: + return initial + try: + f = UploadedFile(data['filename'], data['content']) + except TypeError: + raise ValidationError(self.error_messages['invalid']) + except KeyError: + raise ValidationError(self.error_messages['missing']) + if not f.content: + raise ValidationError(self.error_messages['empty']) + return f + +class ImageField(FileField): + default_error_messages = { + 'invalid_image': _(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."), + } + + def clean(self, data, initial=None): + """ + Checks that the file-upload field data contains a valid image (GIF, JPG, + PNG, possibly others -- whatever the Python Imaging Library supports). + """ + f = super(ImageField, self).clean(data, initial) + if f is None: + return None + elif not data and initial: + return initial + from PIL import Image + from cStringIO import StringIO + try: + # load() is the only method that can spot a truncated JPEG, + # but it cannot be called sanely after verify() + trial_image = Image.open(StringIO(f.content)) + trial_image.load() + # verify() is the only method that can spot a corrupt PNG, + # but it must be called immediately after the constructor + trial_image = Image.open(StringIO(f.content)) + trial_image.verify() + except Exception: # Python Imaging Library doesn't recognize it as an image + raise ValidationError(self.error_messages['invalid_image']) + return f + +url_re = re.compile( + r'^https?://' # http:// or https:// + r'(?:(?:[A-Z0-9-]+\.)+[A-Z]{2,6}|' #domain... + r'localhost|' #localhost... + r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip + r'(?::\d+)?' # optional port + r'(?:/?|/\S+)$', re.IGNORECASE) + +class URLField(RegexField): + default_error_messages = { + 'invalid': _(u'Enter a valid URL.'), + 'invalid_link': _(u'This URL appears to be a broken link.'), + } + + def __init__(self, max_length=None, min_length=None, verify_exists=False, + validator_user_agent=URL_VALIDATOR_USER_AGENT, *args, **kwargs): + super(URLField, self).__init__(url_re, max_length, min_length, *args, + **kwargs) + self.verify_exists = verify_exists + self.user_agent = validator_user_agent + + def clean(self, value): + # If no URL scheme given, assume http:// + if value and '://' not in value: + value = u'http://%s' % value + value = super(URLField, self).clean(value) + if value == u'': + return value + if self.verify_exists: + import urllib2 + from django.conf import settings + headers = { + "Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", + "Accept-Language": "en-us,en;q=0.5", + "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", + "Connection": "close", + "User-Agent": self.user_agent, + } + try: + req = urllib2.Request(value, None, headers) + u = urllib2.urlopen(req) + except ValueError: + raise ValidationError(self.error_messages['invalid']) + except: # urllib2.URLError, httplib.InvalidURL, etc. + raise ValidationError(self.error_messages['invalid_link']) + return value + +class BooleanField(Field): + widget = CheckboxInput + + def clean(self, value): + """Returns a Python boolean object.""" + super(BooleanField, self).clean(value) + # Explicitly check for the string 'False', which is what a hidden field + # will submit for False. Because bool("True") == True, we don't need to + # handle that explicitly. + if value == 'False': + return False + return bool(value) + +class NullBooleanField(BooleanField): + """ + A field whose valid values are None, True and False. Invalid values are + cleaned to None. + """ + widget = NullBooleanSelect + + def clean(self, value): + return {True: True, False: False}.get(value, None) + +class ChoiceField(Field): + widget = Select + default_error_messages = { + 'invalid_choice': _(u'Select a valid choice. That choice is not one of the available choices.'), + } + + def __init__(self, choices=(), required=True, widget=None, label=None, + initial=None, help_text=None, *args, **kwargs): + super(ChoiceField, self).__init__(required, widget, label, initial, + help_text, *args, **kwargs) + self.choices = choices + + def _get_choices(self): + return self._choices + + def _set_choices(self, value): + # Setting choices also sets the choices on the widget. + # choices can be any iterable, but we call list() on it because + # it will be consumed more than once. + self._choices = self.widget.choices = list(value) + + choices = property(_get_choices, _set_choices) + + def clean(self, value): + """ + Validates that the input is in self.choices. + """ + value = super(ChoiceField, self).clean(value) + if value in EMPTY_VALUES: + value = u'' + value = smart_unicode(value) + if value == u'': + return value + valid_values = set([smart_unicode(k) for k, v in self.choices]) + if value not in valid_values: + raise ValidationError(self.error_messages['invalid_choice'] % {'value': value}) + return value + +class MultipleChoiceField(ChoiceField): + hidden_widget = MultipleHiddenInput + widget = SelectMultiple + default_error_messages = { + 'invalid_choice': _(u'Select a valid choice. %(value)s is not one of the available choices.'), + 'invalid_list': _(u'Enter a list of values.'), + } + + def clean(self, value): + """ + Validates that the input is a list or tuple. + """ + if self.required and not value: + raise ValidationError(self.error_messages['required']) + elif not self.required and not value: + return [] + if not isinstance(value, (list, tuple)): + raise ValidationError(self.error_messages['invalid_list']) + new_value = [smart_unicode(val) for val in value] + # Validate that each value in the value list is in self.choices. + valid_values = set([smart_unicode(k) for k, v in self.choices]) + for val in new_value: + if val not in valid_values: + raise ValidationError(self.error_messages['invalid_choice'] % {'value': val}) + return new_value + +class ComboField(Field): + """ + A Field whose clean() method calls multiple Field clean() methods. + """ + def __init__(self, fields=(), *args, **kwargs): + super(ComboField, self).__init__(*args, **kwargs) + # Set 'required' to False on the individual fields, because the + # required validation will be handled by ComboField, not by those + # individual fields. + for f in fields: + f.required = False + self.fields = fields + + def clean(self, value): + """ + Validates the given value against all of self.fields, which is a + list of Field instances. + """ + super(ComboField, self).clean(value) + for field in self.fields: + value = field.clean(value) + return value + +class MultiValueField(Field): + """ + A Field that aggregates the logic of multiple Fields. + + Its clean() method takes a "decompressed" list of values, which are then + cleaned into a single value according to self.fields. Each value in + this list is cleaned by the corresponding field -- the first value is + cleaned by the first field, the second value is cleaned by the second + field, etc. Once all fields are cleaned, the list of clean values is + "compressed" into a single value. + + Subclasses should not have to implement clean(). Instead, they must + implement compress(), which takes a list of valid values and returns a + "compressed" version of those values -- a single value. + + You'll probably want to use this with MultiWidget. + """ + default_error_messages = { + 'invalid': _(u'Enter a list of values.'), + } + + def __init__(self, fields=(), *args, **kwargs): + super(MultiValueField, self).__init__(*args, **kwargs) + # Set 'required' to False on the individual fields, because the + # required validation will be handled by MultiValueField, not by those + # individual fields. + for f in fields: + f.required = False + self.fields = fields + + def clean(self, value): + """ + Validates every value in the given list. A value is validated against + the corresponding Field in self.fields. + + For example, if this MultiValueField was instantiated with + fields=(DateField(), TimeField()), clean() would call + DateField.clean(value[0]) and TimeField.clean(value[1]). + """ + cleaned_data = [] + errors = ErrorList() + if not value or isinstance(value, (list, tuple)): + if not value or not [v for v in value if v not in EMPTY_VALUES]: + if self.required: + raise ValidationError(self.error_messages['required']) + else: + return self.compress([]) + else: + raise ValidationError(self.error_messages['invalid']) + for i, field in enumerate(self.fields): + try: + field_value = value[i] + except IndexError: + field_value = None + if self.required and field_value in EMPTY_VALUES: + raise ValidationError(self.error_messages['required']) + try: + cleaned_data.append(field.clean(field_value)) + except ValidationError, e: + # Collect all validation errors in a single list, which we'll + # raise at the end of clean(), rather than raising a single + # exception for the first error we encounter. + errors.extend(e.messages) + if errors: + raise ValidationError(errors) + return self.compress(cleaned_data) + + def compress(self, data_list): + """ + Returns a single value for the given list of values. The values can be + assumed to be valid. + + For example, if this MultiValueField was instantiated with + fields=(DateField(), TimeField()), this might return a datetime + object created by combining the date and time in data_list. + """ + raise NotImplementedError('Subclasses must implement this method.') + +class FilePathField(ChoiceField): + def __init__(self, path, match=None, recursive=False, required=True, + widget=Select, label=None, initial=None, help_text=None, + *args, **kwargs): + self.path, self.match, self.recursive = path, match, recursive + super(FilePathField, self).__init__(choices=(), required=required, + widget=widget, label=label, initial=initial, help_text=help_text, + *args, **kwargs) + self.choices = [] + if self.match is not None: + self.match_re = re.compile(self.match) + if recursive: + for root, dirs, files in os.walk(self.path): + for f in files: + if self.match is None or self.match_re.search(f): + f = os.path.join(root, f) + self.choices.append((f, f.replace(path, "", 1))) + else: + try: + for f in os.listdir(self.path): + full_file = os.path.join(self.path, f) + if os.path.isfile(full_file) and (self.match is None or self.match_re.search(f)): + self.choices.append((full_file, f)) + except OSError: + pass + self.widget.choices = self.choices + +class SplitDateTimeField(MultiValueField): + default_error_messages = { + 'invalid_date': _(u'Enter a valid date.'), + 'invalid_time': _(u'Enter a valid time.'), + } + + def __init__(self, *args, **kwargs): + errors = self.default_error_messages.copy() + if 'error_messages' in kwargs: + errors.update(kwargs['error_messages']) + fields = ( + DateField(error_messages={'invalid': errors['invalid_date']}), + TimeField(error_messages={'invalid': errors['invalid_time']}), + ) + super(SplitDateTimeField, self).__init__(fields, *args, **kwargs) + + def compress(self, data_list): + if data_list: + # Raise a validation error if time or date is empty + # (possible if SplitDateTimeField has required=False). + if data_list[0] in EMPTY_VALUES: + raise ValidationError(self.error_messages['invalid_date']) + if data_list[1] in EMPTY_VALUES: + raise ValidationError(self.error_messages['invalid_time']) + return datetime.datetime.combine(*data_list) + return None + +ipv4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$') + +class IPAddressField(RegexField): + default_error_messages = { + 'invalid': _(u'Enter a valid IPv4 address.'), + } + + def __init__(self, *args, **kwargs): + super(IPAddressField, self).__init__(ipv4_re, *args, **kwargs) diff --git a/deluge/ui/webui/lib/newforms_portable/forms.py b/deluge/ui/webui/lib/newforms_portable/forms.py new file mode 100644 index 000000000..2c481e47a --- /dev/null +++ b/deluge/ui/webui/lib/newforms_portable/forms.py @@ -0,0 +1,350 @@ +""" +Form classes +""" + +from copy import deepcopy + +from django.utils.datastructures import SortedDict +from django.utils.html import escape +from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode +from django.utils.safestring import mark_safe + +from fields import Field, FileField +from widgets import TextInput, Textarea +from util import flatatt, ErrorDict, ErrorList, ValidationError + +__all__ = ('BaseForm', 'Form') + +NON_FIELD_ERRORS = '__all__' + +def pretty_name(name): + "Converts 'first_name' to 'First name'" + name = name[0].upper() + name[1:] + return name.replace('_', ' ') + +def get_declared_fields(bases, attrs, with_base_fields=True): + """ + Create a list of form field instances from the passed in 'attrs', plus any + similar fields on the base classes (in 'bases'). This is used by both the + Form and ModelForm metclasses. + + If 'with_base_fields' is True, all fields from the bases are used. + Otherwise, only fields in the 'declared_fields' attribute on the bases are + used. The distinction is useful in ModelForm subclassing. + """ + fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)] + fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter)) + + # If this class is subclassing another Form, add that Form's fields. + # Note that we loop over the bases in *reverse*. This is necessary in + # order to preserve the correct order of fields. + if with_base_fields: + for base in bases[::-1]: + if hasattr(base, 'base_fields'): + fields = base.base_fields.items() + fields + else: + for base in bases[::-1]: + if hasattr(base, 'declared_fields'): + fields = base.declared_fields.items() + fields + + return SortedDict(fields) + +class DeclarativeFieldsMetaclass(type): + """ + Metaclass that converts Field attributes to a dictionary called + 'base_fields', taking into account parent class 'base_fields' as well. + """ + def __new__(cls, name, bases, attrs): + attrs['base_fields'] = get_declared_fields(bases, attrs) + return type.__new__(cls, name, bases, attrs) + +class BaseForm(StrAndUnicode): + # This is the main implementation of all the Form logic. Note that this + # class is different than Form. See the comments by the Form class for more + # information. Any improvements to the form API should be made to *this* + # class, not to the Form class. + def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, + initial=None, error_class=ErrorList, label_suffix=':'): + self.is_bound = data is not None or files is not None + self.data = data or {} + self.files = files or {} + self.auto_id = auto_id + self.prefix = prefix + self.initial = initial or {} + self.error_class = error_class + self.label_suffix = label_suffix + self._errors = None # Stores the errors after clean() has been called. + + # The base_fields class attribute is the *class-wide* definition of + # fields. Because a particular *instance* of the class might want to + # alter self.fields, we create self.fields here by copying base_fields. + # Instances should always modify self.fields; they should not modify + # self.base_fields. + self.fields = deepcopy(self.base_fields) + + def __unicode__(self): + return self.as_table() + + def __iter__(self): + for name, field in self.fields.items(): + yield BoundField(self, field, name) + + def __getitem__(self, name): + "Returns a BoundField with the given name." + try: + field = self.fields[name] + except KeyError: + raise KeyError('Key %r not found in Form' % name) + return BoundField(self, field, name) + + def _get_errors(self): + "Returns an ErrorDict for the data provided for the form" + if self._errors is None: + self.full_clean() + return self._errors + errors = property(_get_errors) + + def is_valid(self): + """ + Returns True if the form has no errors. Otherwise, False. If errors are + being ignored, returns False. + """ + return self.is_bound and not bool(self.errors) + + def add_prefix(self, field_name): + """ + Returns the field name with a prefix appended, if this Form has a + prefix set. + + Subclasses may wish to override. + """ + return self.prefix and ('%s-%s' % (self.prefix, field_name)) or field_name + + def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row): + "Helper function for outputting HTML. Used by as_table(), as_ul(), as_p()." + top_errors = self.non_field_errors() # Errors that should be displayed above all fields. + output, hidden_fields = [], [] + for name, field in self.fields.items(): + bf = BoundField(self, field, name) + bf_errors = self.error_class([escape(error) for error in bf.errors]) # Escape and cache in local variable. + if bf.is_hidden: + if bf_errors: + top_errors.extend([u'(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors]) + hidden_fields.append(unicode(bf)) + else: + if errors_on_separate_row and bf_errors: + output.append(error_row % force_unicode(bf_errors)) + if bf.label: + label = escape(force_unicode(bf.label)) + # Only add the suffix if the label does not end in + # punctuation. + if self.label_suffix: + if label[-1] not in ':?.!': + label += self.label_suffix + label = bf.label_tag(label) or '' + else: + label = '' + if field.help_text: + help_text = help_text_html % force_unicode(field.help_text) + else: + help_text = u'' + output.append(normal_row % {'errors': force_unicode(bf_errors), 'label': force_unicode(label), 'field': unicode(bf), 'help_text': help_text}) + if top_errors: + output.insert(0, error_row % force_unicode(top_errors)) + if hidden_fields: # Insert any hidden fields in the last row. + str_hidden = u''.join(hidden_fields) + if output: + last_row = output[-1] + # Chop off the trailing row_ender (e.g. '') and + # insert the hidden fields. + output[-1] = last_row[:-len(row_ender)] + str_hidden + row_ender + else: + # If there aren't any rows in the output, just append the + # hidden fields. + output.append(str_hidden) + return mark_safe(u'\n'.join(output)) + + def as_table(self): + "Returns this form rendered as HTML s -- excluding the
      ." + return self._html_output(u'%(label)s%(errors)s%(field)s%(help_text)s', u'%s', '', u'
      %s', False) + + def as_ul(self): + "Returns this form rendered as HTML
    • s -- excluding the
        ." + return self._html_output(u'
      • %(errors)s%(label)s %(field)s%(help_text)s
      • ', u'
      • %s
      • ', '', u' %s', False) + + def as_p(self): + "Returns this form rendered as HTML

        s." + return self._html_output(u'

        %(label)s %(field)s%(help_text)s

        ', u'%s', '

        ', u' %s', True) + + def non_field_errors(self): + """ + Returns an ErrorList of errors that aren't associated with a particular + field -- i.e., from Form.clean(). Returns an empty ErrorList if there + are none. + """ + return self.errors.get(NON_FIELD_ERRORS, self.error_class()) + + def full_clean(self): + """ + Cleans all of self.data and populates self._errors and + self.cleaned_data. + """ + self._errors = ErrorDict() + if not self.is_bound: # Stop further processing. + return + self.cleaned_data = {} + for name, field in self.fields.items(): + # value_from_datadict() gets the data from the data dictionaries. + # Each widget type knows how to retrieve its own data, because some + # widgets split data over several HTML fields. + value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) + try: + if isinstance(field, FileField): + initial = self.initial.get(name, field.initial) + value = field.clean(value, initial) + else: + value = field.clean(value) + self.cleaned_data[name] = value + if hasattr(self, 'clean_%s' % name): + value = getattr(self, 'clean_%s' % name)() + self.cleaned_data[name] = value + except ValidationError, e: + self._errors[name] = e.messages + if name in self.cleaned_data: + del self.cleaned_data[name] + try: + self.cleaned_data = self.clean() + except ValidationError, e: + self._errors[NON_FIELD_ERRORS] = e.messages + if self._errors: + delattr(self, 'cleaned_data') + + def clean(self): + """ + Hook for doing any extra form-wide cleaning after Field.clean() been + called on every field. Any ValidationError raised by this method will + not be associated with a particular field; it will have a special-case + association with the field named '__all__'. + """ + return self.cleaned_data + + def is_multipart(self): + """ + Returns True if the form needs to be multipart-encrypted, i.e. it has + FileInput. Otherwise, False. + """ + for field in self.fields.values(): + if field.widget.needs_multipart_form: + return True + return False + +class Form(BaseForm): + "A collection of Fields, plus their associated data." + # This is a separate class from BaseForm in order to abstract the way + # self.fields is specified. This class (Form) is the one that does the + # fancy metaclass stuff purely for the semantic sugar -- it allows one + # to define a form using declarative syntax. + # BaseForm itself has no way of designating self.fields. + __metaclass__ = DeclarativeFieldsMetaclass + +class BoundField(StrAndUnicode): + "A Field plus data" + def __init__(self, form, field, name): + self.form = form + self.field = field + self.name = name + self.html_name = form.add_prefix(name) + if self.field.label is None: + self.label = pretty_name(name) + else: + self.label = self.field.label + self.help_text = field.help_text or '' + + def __unicode__(self): + """Renders this field as an HTML widget.""" + return self.as_widget() + + def _errors(self): + """ + Returns an ErrorList for this field. Returns an empty ErrorList + if there are none. + """ + return self.form.errors.get(self.name, self.form.error_class()) + errors = property(_errors) + + def as_widget(self, widget=None, attrs=None): + """ + Renders the field by rendering the passed widget, adding any HTML + attributes passed as attrs. If no widget is specified, then the + field's default widget will be used. + """ + if not widget: + widget = self.field.widget + attrs = attrs or {} + auto_id = self.auto_id + if auto_id and 'id' not in attrs and 'id' not in widget.attrs: + attrs['id'] = auto_id + if not self.form.is_bound: + data = self.form.initial.get(self.name, self.field.initial) + if callable(data): + data = data() + else: + data = self.data + return widget.render(self.html_name, data, attrs=attrs) + + def as_text(self, attrs=None): + """ + Returns a string of HTML for representing this as an . + """ + return self.as_widget(TextInput(), attrs) + + def as_textarea(self, attrs=None): + "Returns a string of HTML for representing this as a ' % (flatatt(final_attrs), + conditional_escape(force_unicode(value)))) + +class DateTimeInput(Input): + input_type = 'text' + format = '%Y-%m-%d %H:%M:%S' # '2006-10-25 14:30:59' + + def __init__(self, attrs=None, format=None): + super(DateTimeInput, self).__init__(attrs) + if format: + self.format = format + + def render(self, name, value, attrs=None): + if value is None: + value = '' + elif hasattr(value, 'strftime'): + value = value.strftime(self.format) + return super(DateTimeInput, self).render(name, value, attrs) + +class CheckboxInput(Widget): + def __init__(self, attrs=None, check_test=bool): + super(CheckboxInput, self).__init__(attrs) + # check_test is a callable that takes a value and returns True + # if the checkbox should be checked for that value. + self.check_test = check_test + + def render(self, name, value, attrs=None): + final_attrs = self.build_attrs(attrs, type='checkbox', name=name) + try: + result = self.check_test(value) + except: # Silently catch exceptions + result = False + if result: + final_attrs['checked'] = 'checked' + if value not in ('', True, False, None): + # Only add the 'value' attribute if a value is non-empty. + final_attrs['value'] = force_unicode(value) + return mark_safe(u'' % flatatt(final_attrs)) + + def value_from_datadict(self, data, files, name): + if name not in data: + # A missing value means False because HTML form submission does not + # send results for unselected checkboxes. + return False + return super(CheckboxInput, self).value_from_datadict(data, files, name) + +class Select(Widget): + def __init__(self, attrs=None, choices=()): + super(Select, self).__init__(attrs) + # choices can be any iterable, but we may need to render this widget + # multiple times. Thus, collapse it into a list so it can be consumed + # more than once. + self.choices = list(choices) + + def render(self, name, value, attrs=None, choices=()): + if value is None: value = '' + final_attrs = self.build_attrs(attrs, name=name) + output = [u'' % flatatt(final_attrs)] + # Normalize to string. + str_value = force_unicode(value) + for option_value, option_label in chain(self.choices, choices): + option_value = force_unicode(option_value) + selected_html = (option_value == str_value) and u' selected="selected"' or '' + output.append(u'' % ( + escape(option_value), selected_html, + conditional_escape(force_unicode(option_label)))) + output.append(u'') + return mark_safe(u'\n'.join(output)) + +class NullBooleanSelect(Select): + """ + A Select Widget intended to be used with NullBooleanField. + """ + def __init__(self, attrs=None): + choices = ((u'1', ugettext('Unknown')), (u'2', ugettext('Yes')), (u'3', ugettext('No'))) + super(NullBooleanSelect, self).__init__(attrs, choices) + + def render(self, name, value, attrs=None, choices=()): + try: + value = {True: u'2', False: u'3', u'2': u'2', u'3': u'3'}[value] + except KeyError: + value = u'1' + return super(NullBooleanSelect, self).render(name, value, attrs, choices) + + def value_from_datadict(self, data, files, name): + value = data.get(name, None) + return {u'2': True, u'3': False, True: True, False: False}.get(value, None) + +class SelectMultiple(Widget): + def __init__(self, attrs=None, choices=()): + super(SelectMultiple, self).__init__(attrs) + # choices can be any iterable + self.choices = choices + + def render(self, name, value, attrs=None, choices=()): + if value is None: value = [] + final_attrs = self.build_attrs(attrs, name=name) + output = [u'') + return mark_safe(u'\n'.join(output)) + + def value_from_datadict(self, data, files, name): + if isinstance(data, MultiValueDict): + return data.getlist(name) + return data.get(name, None) + +class RadioInput(StrAndUnicode): + """ + An object used by RadioFieldRenderer that represents a single + . + """ + + def __init__(self, name, value, attrs, choice, index): + self.name, self.value = name, value + self.attrs = attrs + self.choice_value = force_unicode(choice[0]) + self.choice_label = force_unicode(choice[1]) + self.index = index + + def __unicode__(self): + return mark_safe(u'' % (self.tag(), + conditional_escape(force_unicode(self.choice_label)))) + + def is_checked(self): + return self.value == self.choice_value + + def tag(self): + if 'id' in self.attrs: + self.attrs['id'] = '%s_%s' % (self.attrs['id'], self.index) + final_attrs = dict(self.attrs, type='radio', name=self.name, value=self.choice_value) + if self.is_checked(): + final_attrs['checked'] = 'checked' + return mark_safe(u'' % flatatt(final_attrs)) + +class RadioFieldRenderer(StrAndUnicode): + """ + An object used by RadioSelect to enable customization of radio widgets. + """ + + def __init__(self, name, value, attrs, choices): + self.name, self.value, self.attrs = name, value, attrs + self.choices = choices + + def __iter__(self): + for i, choice in enumerate(self.choices): + yield RadioInput(self.name, self.value, self.attrs.copy(), choice, i) + + def __getitem__(self, idx): + choice = self.choices[idx] # Let the IndexError propogate + return RadioInput(self.name, self.value, self.attrs.copy(), choice, idx) + + def __unicode__(self): + return self.render() + + def render(self): + """Outputs a
        +

        Console UI

        +
          +
        • sadrul
        -*and all other authors/helpers/contributors I forgot to mention. + +
        +*and all other authors/helpers/contributors I forgot to mention $:render.footer() diff --git a/deluge/ui/webui/templates/classic/admin_toolbar.html b/deluge/ui/webui/templates/classic/admin_toolbar.html new file mode 100644 index 000000000..b2d1f732d --- /dev/null +++ b/deluge/ui/webui/templates/classic/admin_toolbar.html @@ -0,0 +1,10 @@ +$def with (active_tab) +
        +$for id, title, url in admin_pages: + $title +
        diff --git a/plugins/WebUi/templates/deluge/authors.txt b/deluge/ui/webui/templates/classic/authors.txt similarity index 100% rename from plugins/WebUi/templates/deluge/authors.txt rename to deluge/ui/webui/templates/classic/authors.txt diff --git a/deluge/ui/webui/templates/classic/config.html b/deluge/ui/webui/templates/classic/config.html new file mode 100644 index 000000000..1b96535b6 --- /dev/null +++ b/deluge/ui/webui/templates/classic/config.html @@ -0,0 +1,44 @@ +$def with (groups, pages, form, selected, message, error) + +$:render.header(_("Config"), 'config') + +$:render.admin_toolbar('config') + +
        +$for group in groups: +

        $group

        + +
        + +
        +

        $form.group / $form.title

        +
        $form.info
        +
        +$:form.pre_html() + +$:form.as_table() + + + + + +
        + +$if message: +
        $message
        +$if error: +
        $error
        + +$:form.post_html() + +
        + +
        +$:render.footer() diff --git a/deluge/ui/webui/templates/classic/connect.html b/deluge/ui/webui/templates/classic/connect.html new file mode 100644 index 000000000..b4e992305 --- /dev/null +++ b/deluge/ui/webui/templates/classic/connect.html @@ -0,0 +1,58 @@ +$def with (connect_list, connected, restart) + +$:render.header(_("Connect to Daemon"), 'connect') + +$:render.admin_toolbar('connect') + +
        +

        $_("Connect")

        +$if connected: + +
        + $_('Connected to') + $connected + + +
        +$else: +
        $_("Not Connected to a daemon") +
        + + +
        +$for i, uri in enumerate(connect_list): +

        $uri

        +

        + $_("Other"): + +

        + + + + +
        +
        + +
        +$:render.footer() diff --git a/plugins/WebUi/templates/deluge/error.html b/deluge/ui/webui/templates/classic/error.html similarity index 100% rename from plugins/WebUi/templates/deluge/error.html rename to deluge/ui/webui/templates/classic/error.html diff --git a/plugins/WebUi/templates/deluge/footer.html b/deluge/ui/webui/templates/classic/footer.html similarity index 100% rename from plugins/WebUi/templates/deluge/footer.html rename to deluge/ui/webui/templates/classic/footer.html diff --git a/deluge/ui/webui/templates/classic/header.html b/deluge/ui/webui/templates/classic/header.html new file mode 100644 index 000000000..eff4c8dd5 --- /dev/null +++ b/deluge/ui/webui/templates/classic/header.html @@ -0,0 +1,23 @@ +$def with (title, active_tab="NONE") + + + Deluge:$title + + + + + + + +
        + + + + +
        + +
        +
        diff --git a/plugins/WebUi/templates/deluge/index.html b/deluge/ui/webui/templates/classic/index.html similarity index 70% rename from plugins/WebUi/templates/deluge/index.html rename to deluge/ui/webui/templates/classic/index.html index 1d52dd6b0..92f98e330 100644 --- a/plugins/WebUi/templates/deluge/index.html +++ b/deluge/ui/webui/templates/classic/index.html @@ -1,10 +1,14 @@ -$def with (torrent_list, all_torrents) -$:render.header(_('Torrent list')) +$def with (torrent_list, organize_filters) +$:render.header(_('Torrent list'), 'home') + + +$if organize_filters: + $:render.part_organize(organize_filters) - $:(sort_head('calc_state_str', 'S')) - $:(sort_head('queue_pos', '#')) + $:(sort_head('state', 'S')) + $:(sort_head('queue', '#')) $:(sort_head('name', _('Name'))) $:(sort_head('total_size', _('Size'))) $:(sort_head('progress', _('Progress'))) @@ -13,34 +17,34 @@ $:render.header(_('Torrent list')) $:(sort_head('download_rate', _('Download'))) $:(sort_head('upload_rate', _('Upload'))) $:(sort_head('eta', _('Eta'))) - $:(sort_head('distributed_copies', _('Avail'))) + $:(sort_head('distributed_copies', _('Ava'))) $:(sort_head('ratio', _('Ratio'))) $#4-space indentation is mandatory for for-loops in templetor! $for torrent in torrent_list: - + - - - + + + diff --git a/plugins/WebUi/templates/deluge/login.html b/deluge/ui/webui/templates/classic/login.html similarity index 57% rename from plugins/WebUi/templates/deluge/login.html rename to deluge/ui/webui/templates/classic/login.html index 0436e9076..fd2febfe8 100644 --- a/plugins/WebUi/templates/deluge/login.html +++ b/deluge/ui/webui/templates/classic/login.html @@ -1,24 +1,26 @@ $def with (error) $:render.header(_('Login'))
        +

        $_("Deluge Login")

        + $if error > 0:
        $_("Password is invalid,try again")
        -
        +
        -
        - $_('Password') +
        -
        +
        $torrent.queue_pos$torrent.queue - + $(crop(torrent.name, 40)) $fsize(torrent.total_size)
        - $torrent.message $int(torrent.progress) % + $_(torrent.state) $int(torrent.progress) %
        $torrent.num_seeds ($torrent.total_seeds) $torrent.num_peers ($torrent.total_peers)$fspeed(torrent.download_rate)$fspeed(torrent.upload_rate)$torrent.eta$fspeed(torrent.download_payload_rate)$fspeed(torrent.upload_payload_rate)$ftime(torrent.eta) $("%.3f" % torrent.distributed_copies) $("%.3f" % torrent.ratio)
        + + diff --git a/deluge/ui/webui/templates/classic/meta.cfg b/deluge/ui/webui/templates/classic/meta.cfg new file mode 100644 index 000000000..2965a1b5e --- /dev/null +++ b/deluge/ui/webui/templates/classic/meta.cfg @@ -0,0 +1,10 @@ +{ + 'authors':['Martijn Voncken '], + 'inherits':[], + 'comment':"""Fail-safe template. + Most other templetes inherit from this template. + Should work on ANY browser. + thanks to "somedude" for some help/enhancements in header/footer/css. + """ +} + diff --git a/plugins/WebUi/templates/deluge/part_button.html b/deluge/ui/webui/templates/classic/part_button.html similarity index 54% rename from plugins/WebUi/templates/deluge/part_button.html rename to deluge/ui/webui/templates/classic/part_button.html index 8c420560f..9acdf5afd 100644 --- a/plugins/WebUi/templates/deluge/part_button.html +++ b/deluge/ui/webui/templates/classic/part_button.html @@ -1,23 +1,23 @@ $def with (method, url, title, image='')
        -
        + -$if (get_config('button_style') == 0): +$if (int(get_config('button_style')) == 0): -$if (get_config('button_style') == 1): +$if (int(get_config('button_style')) == 1): $if image: - + $else: -$if (get_config('button_style') == 2): +$if (int(get_config('button_style')) == 2): diff --git a/deluge/ui/webui/templates/classic/part_organize.html b/deluge/ui/webui/templates/classic/part_organize.html new file mode 100644 index 000000000..d73c5e6fd --- /dev/null +++ b/deluge/ui/webui/templates/classic/part_organize.html @@ -0,0 +1,2 @@ +$def with (filters) + diff --git a/plugins/WebUi/templates/advanced/part_stats.html b/deluge/ui/webui/templates/classic/part_stats.html similarity index 88% rename from plugins/WebUi/templates/advanced/part_stats.html rename to deluge/ui/webui/templates/classic/part_stats.html index 01c0fcd52..04be706c6 100644 --- a/plugins/WebUi/templates/advanced/part_stats.html +++ b/deluge/ui/webui/templates/classic/part_stats.html @@ -14,10 +14,10 @@ $else: $#end $:render.part_button('POST', '/logout', _('Logout'), 'tango/system-log-out.png') +
        - $_('Connections') : $stats.num_connections ($stats.max_num_connections) @@ -25,14 +25,8 @@ $:render.part_button('POST', '/logout', _('Logout'), 'tango/system-log-out.png') $_('Up Speed') : $stats.upload_rate ($stats.max_upload) - - + $:render.part_button('GET', '/config/', _('Settings'), 'tango/preferences-system.png')
        - - - diff --git a/plugins/WebUi/templates/deluge/refresh_form.html b/deluge/ui/webui/templates/classic/refresh_form.html similarity index 84% rename from plugins/WebUi/templates/deluge/refresh_form.html rename to deluge/ui/webui/templates/classic/refresh_form.html index 0ac2cffda..42c2d2c6f 100644 --- a/plugins/WebUi/templates/deluge/refresh_form.html +++ b/deluge/ui/webui/templates/classic/refresh_form.html @@ -1,6 +1,6 @@ $:render.header(_('Set Timeout'))
        - + $_('Refresh page every:') diff --git a/deluge/ui/webui/templates/classic/sort_column_head.html b/deluge/ui/webui/templates/classic/sort_column_head.html new file mode 100644 index 000000000..e12b447ad --- /dev/null +++ b/deluge/ui/webui/templates/classic/sort_column_head.html @@ -0,0 +1,12 @@ +$def with (column_id, column_name, order, active_up, active_down) +
        + + diff --git a/deluge/ui/webui/templates/classic/tab_details.html b/deluge/ui/webui/templates/classic/tab_details.html new file mode 100644 index 000000000..a1e5be09b --- /dev/null +++ b/deluge/ui/webui/templates/classic/tab_details.html @@ -0,0 +1,47 @@ +$def with (torrent) +
        + $_('Password') + - -
        - +
        +   + - - -
        - $_('About') +
        + +$column_name\ +$if active_up: + +$if active_down: + + +
        + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        $('Name'):$torrent.name
        $('Hash'):$torrent.id
        $('Save Path'):$crop_left(torrent.save_path, 200)
        $_('Total Size'):$fsize(torrent.total_size)
        $_('# Of Files'):$torrent.num_files
        $_('Tracker Status'):$(crop(torrent.tracker_status, 200))
        $_('Tracker'):$(crop(torrent.tracker, 200))
        $_('Private'):$torrent.private
        + + diff --git a/deluge/ui/webui/templates/classic/tab_files.html b/deluge/ui/webui/templates/classic/tab_files.html new file mode 100644 index 000000000..27d780dd0 --- /dev/null +++ b/deluge/ui/webui/templates/classic/tab_files.html @@ -0,0 +1,35 @@ +$def with (torrent, redirect=None) + +$if redirect: + +$else: + + + + +$altrow(True) + + + + + + + + + +$for i, file in enumerate(torrent.files): + + + + + $for prio in [0, 1, 2, 5]: + + +
        $_("File")$_("Size")$_("Progress")$_("X")$_("N")$_("+")$_("++")
        + $(crop_left(file["path"], 60)) + $fsize(file["size"])$int(torrent.file_progress[i] * 100)%
        + + diff --git a/deluge/ui/webui/templates/classic/tab_options.html b/deluge/ui/webui/templates/classic/tab_options.html new file mode 100644 index 000000000..5ea736fdf --- /dev/null +++ b/deluge/ui/webui/templates/classic/tab_options.html @@ -0,0 +1,21 @@ +$def with (torrent) +
        + +
        + + $:(forms.torrent_options(torrent).as_table(["max_download_speed", "max_upload_speed", "max_connections", "max_upload_slots"])) + + + +
        +
        + + + $:(forms.torrent_options(torrent).as_table(["prioritize_first_last", "private"])) +
        + + +
        + +
        + diff --git a/deluge/ui/webui/templates/classic/tab_peers.html b/deluge/ui/webui/templates/classic/tab_peers.html new file mode 100644 index 000000000..4ee94d0e1 --- /dev/null +++ b/deluge/ui/webui/templates/classic/tab_peers.html @@ -0,0 +1,36 @@ +$def with (torrent) +
        + + + +$altrow(True) + + + + + + + + +$for peer in torrent.peers: + + + + + + + + +
        $_("Ip")$_("Up Speed")$_("Down Speed")$_("Country")$_("Client")$_("Progress")
        $peer['ip']$fspeed(peer['up_speed'])$fspeed(peer['down_speed'])$peer['country']$peer['client'] + $if peer.get('progress'): +
        +
        + $int(peer['progress']) % +
        +
        + $else: +
        + ? % +
        +
        +
        diff --git a/plugins/WebUi/templates/deluge/tab_meta.html b/deluge/ui/webui/templates/classic/tab_statistics.html similarity index 50% rename from plugins/WebUi/templates/deluge/tab_meta.html rename to deluge/ui/webui/templates/classic/tab_statistics.html index 7cfaf7ff8..b41fed559 100644 --- a/plugins/WebUi/templates/deluge/tab_meta.html +++ b/deluge/ui/webui/templates/classic/tab_statistics.html @@ -1,85 +1,103 @@ $def with (torrent) - -
        +
        - $torrent.progress %
        + $("%.2f" % torrent.progress) %
        +
        - + - + - - + - - - - - - - - -
        $_('Downloaded'):$torrent.calc_total_downloaded
        $fsize(torrent.total_done)
        $_('Uploaded'):$torrent.calc_total_uploaded$fsize(torrent.total_payload_upload)
        $_('Seeders'):$torrent.num_seeds ($torrent.total_seeds )
        $_('Share Ratio'): $("%.3f" % torrent.ratio)
        $_('Pieces'):$torrent.num_pieces x $fsize(torrent.piece_length)
          
        -
        - - - - - - - - - - - - - - - - - - - - - -
        $_('Speed'): -$fspeed(torrent.download_rate)
        $_('Speed'):$fspeed(torrent.upload_rate)
        $_('Peers'):$torrent.num_peers ($torrent.total_peers )
        $_('ETA'):$torrent.eta
        $_('Availability'):$("%.3f" % torrent.distributed_copies)
          
        - -
        - - - - - - - - - - - - - - - - - - -
        $_('Total Size'):$fsize(torrent.total_size)
        $_('# Of Files'):$torrent.num_files
        $_('Tracker'):$(crop(torrent.tracker, 30))
        $_('Tracker Status'):$(crop(torrent.tracker_status, 30))
        $_('Next Announce'): $torrent.next_announce
        $_('Queue Position'):$torrent.queue_pos
        +
        + + + + + + + + + + + + + + + + +
        $_('Speed'): +$fspeed(torrent.download_payload_rate)
        $_('Speed'):$fspeed(torrent.upload_payload_rate)
        $_('ETA'):$ftime(torrent.eta)
        $_('Pieces'):$torrent.num_pieces ($fsize(torrent.piece_length))
        + + + + + + + + + + + + + + + + + + + + + +
        $_('Seeders'):$torrent.num_seeds ($torrent.total_seeds )
        $_('Peers'):$torrent.num_peers ($torrent.total_peers )
        $_('Availability'):$("%.3f" % torrent.distributed_copies)
        $_('Queue Position'): +$if (torrent.queue == -1): + ∞ +$else: + $(torrent.queue + 1) +
        + + + + + + + + + + + + + + + + +
        $_('Active time'):TODO
        $_('Seeding time'):TODO
        $_('Seed rank'):TODO
        $_('Allocation'): +$if torrent.compact: + $_('Compact') +$else: + $_('Full') +
        + + + + + diff --git a/deluge/ui/webui/templates/classic/tab_trackers.html b/deluge/ui/webui/templates/classic/tab_trackers.html new file mode 100644 index 000000000..0030626dd --- /dev/null +++ b/deluge/ui/webui/templates/classic/tab_trackers.html @@ -0,0 +1,24 @@ +$def with (torrent) +
        + + +$altrow(True) + + + + +$for tracker in torrent.trackers: + + + + + + + + + +
        #$_("Tracker")
        +
        +
        + +
        diff --git a/deluge/ui/webui/templates/classic/torrent_add.html b/deluge/ui/webui/templates/classic/torrent_add.html new file mode 100644 index 000000000..4a5f59e86 --- /dev/null +++ b/deluge/ui/webui/templates/classic/torrent_add.html @@ -0,0 +1,56 @@ +$def with (add_form, options_form, error) +$:render.header(_("Add Torrent")) +
        +

        $_("Add Torrent")

        +
        + + + +$if error: +
        $error
        +
        + + $:add_form.as_table() +
        +$_('Options') + + +
        + + + +
        + + +
        + + +
        + + +$:render.footer() diff --git a/plugins/WebUi/templates/deluge/torrent_delete.html b/deluge/ui/webui/templates/classic/torrent_delete.html similarity index 92% rename from plugins/WebUi/templates/deluge/torrent_delete.html rename to deluge/ui/webui/templates/classic/torrent_delete.html index a9aceb551..46b37701d 100644 --- a/plugins/WebUi/templates/deluge/torrent_delete.html +++ b/deluge/ui/webui/templates/classic/torrent_delete.html @@ -1,7 +1,7 @@ $def with (torrent_ids, torrent_list) $:render.header(_("Remove torrent"))
        -
        +

        $_("Remove torrent")

        diff --git a/deluge/ui/webui/templates/classic/torrent_files.html b/deluge/ui/webui/templates/classic/torrent_files.html new file mode 100644 index 000000000..d6973b470 --- /dev/null +++ b/deluge/ui/webui/templates/classic/torrent_files.html @@ -0,0 +1,14 @@ +$def with (torrent, error) +$:render.header(torrent.name) +
        +
        +

        $_(torrent.name)

        +
          +$:render.tab_files(torrent, True)
        + +$if error: +
        $error
        + + +
        +$:render.footer() \ No newline at end of file diff --git a/deluge/ui/webui/templates/classic/torrent_info.html b/deluge/ui/webui/templates/classic/torrent_info.html new file mode 100644 index 000000000..f996d2140 --- /dev/null +++ b/deluge/ui/webui/templates/classic/torrent_info.html @@ -0,0 +1,17 @@ +$def with (torrent) + +$:(render.header(_(torrent.state) + '/' + torrent.name)) +
        +
        +$for id, title, image, flag, method, url, important in toolbar_items: + $if (flag > 0) and (id != 'details'): + $:render.part_button(method, (url + str(torrent.id)), title, 'tango/' + image) +
        +$for id, title, tab in detail_tabs: +

        $title

        + $:render[tab](torrent) + +
        +
        + +$:render.footer() diff --git a/deluge/ui/webui/templates/classic/torrent_move.html b/deluge/ui/webui/templates/classic/torrent_move.html new file mode 100644 index 000000000..395c2adf6 --- /dev/null +++ b/deluge/ui/webui/templates/classic/torrent_move.html @@ -0,0 +1,22 @@ +$def with (torrent_ids, torrent_list, form, error) +$:render.header(_("Remove torrent")) +
        +
        +
        +

        $_("Move torrent")

        +
          +$for torrent in torrent_list: +
        • $torrent.name ($torrent.save_path)
        • +
        + + +$:form.as_table() + + + + +
        +$:render.footer() \ No newline at end of file diff --git a/plugins/WebUi/templates/hacking-templates.txt b/deluge/ui/webui/templates/hacking-templates.txt similarity index 100% rename from plugins/WebUi/templates/hacking-templates.txt rename to deluge/ui/webui/templates/hacking-templates.txt diff --git a/deluge/ui/webui/templates/white/admin_toolbar.html b/deluge/ui/webui/templates/white/admin_toolbar.html new file mode 100644 index 000000000..0762da65a --- /dev/null +++ b/deluge/ui/webui/templates/white/admin_toolbar.html @@ -0,0 +1,3 @@ +$def with (active_tab) + + diff --git a/deluge/ui/webui/templates/white/footer.html b/deluge/ui/webui/templates/white/footer.html new file mode 100644 index 000000000..9943ff0f8 --- /dev/null +++ b/deluge/ui/webui/templates/white/footer.html @@ -0,0 +1,3 @@ +
        + + diff --git a/deluge/ui/webui/templates/white/header.html b/deluge/ui/webui/templates/white/header.html new file mode 100644 index 000000000..1614ced4a --- /dev/null +++ b/deluge/ui/webui/templates/white/header.html @@ -0,0 +1,50 @@ +$def with (title, active_tab="NONE") + + + + + Deluge:$title + + + + + + + +
        + + + +
        +
        + +       +    + Home + + +$for id, title, url in admin_pages: + $title +Faq +
        + +
        + $#:render.part_auto_refresh() + + + + + $:part_stats() +
        + +
        diff --git a/deluge/ui/webui/templates/white/index.html b/deluge/ui/webui/templates/white/index.html new file mode 100644 index 000000000..9fe7f8e50 --- /dev/null +++ b/deluge/ui/webui/templates/white/index.html @@ -0,0 +1,63 @@ +$def with (torrent_list, label_filters) + + +$:render.header(_("Deluge : Torrent List"), 'home') + +$if label_filters: + + $:render.part_label_filters(label_filters) +$else: +
        + + + + +
        +
        + $:render.part_toolbar() +
        +
        + $:render.part_torrent_list(torrent_list, label_filters) + +
        + + + +
        + + +
        + +
        + + +
        + + + + + + +
        + +
        + +$:render.footer() + + diff --git a/deluge/ui/webui/templates/white/meta.cfg b/deluge/ui/webui/templates/white/meta.cfg new file mode 100644 index 000000000..50a73e48f --- /dev/null +++ b/deluge/ui/webui/templates/white/meta.cfg @@ -0,0 +1,11 @@ +{ + 'authors':['Martijn Voncken '], + 'inherits':['classic'], + 'comment':""" + A more conventional template. + css written from scratch + templated-css with variables. + Inspried by (but not copied from) gmail. + """ +} + diff --git a/deluge/ui/webui/templates/white/part_auto_refresh.html b/deluge/ui/webui/templates/white/part_auto_refresh.html new file mode 100644 index 000000000..7acb24a7c --- /dev/null +++ b/deluge/ui/webui/templates/white/part_auto_refresh.html @@ -0,0 +1,16 @@ +
        +[ +$_('Auto refresh:') +$if getcookie('auto_refresh') == '1': + ($getcookie('auto_refresh_secs')) $_('seconds')   + $_('Set') + $_('Disable') +$else: + $_('Off')   + $_('Enable') +] + + +$_('Admin')   + +
        \ No newline at end of file diff --git a/deluge/ui/webui/templates/white/part_label_filters.html b/deluge/ui/webui/templates/white/part_label_filters.html new file mode 100644 index 000000000..33c48d912 --- /dev/null +++ b/deluge/ui/webui/templates/white/part_label_filters.html @@ -0,0 +1,53 @@ +$def with (filter_items) + +
        + + + +
        +
        +
        $_('Keyword')
        + + +$if get('filter_cat') == "keyword": + $if get('filter_value'): + $_('Clear') + +

        + + +$for cat in ["state", "tracker", "label"]: +
        $cat
        + +
        +
        + + + + diff --git a/deluge/ui/webui/templates/white/part_organize.html b/deluge/ui/webui/templates/white/part_organize.html new file mode 100644 index 000000000..d73c5e6fd --- /dev/null +++ b/deluge/ui/webui/templates/white/part_organize.html @@ -0,0 +1,2 @@ +$def with (filters) + diff --git a/deluge/ui/webui/templates/white/part_stats.html b/deluge/ui/webui/templates/white/part_stats.html new file mode 100644 index 000000000..e72779947 --- /dev/null +++ b/deluge/ui/webui/templates/white/part_stats.html @@ -0,0 +1,14 @@ +$def with (stats) + + +
        + +$stats.num_connections ($deluge_int(stats.max_num_connections)) + +$stats.download_rate ($deluge_int(stats.max_download)) + +$stats.upload_rate ($deluge_int(stats.max_upload)) + +$stats.dht_nodes + +
        diff --git a/deluge/ui/webui/templates/white/part_tab_button.html b/deluge/ui/webui/templates/white/part_tab_button.html new file mode 100644 index 000000000..903f332cd --- /dev/null +++ b/deluge/ui/webui/templates/white/part_tab_button.html @@ -0,0 +1,8 @@ +$def with (id, title, active) + +$if (active == id): + $title + diff --git a/plugins/WebUi/templates/advanced/part_tb_button.html b/deluge/ui/webui/templates/white/part_tb_button.html similarity index 68% rename from plugins/WebUi/templates/advanced/part_tb_button.html rename to deluge/ui/webui/templates/white/part_tb_button.html index bc5ec9a21..6b7169dca 100644 --- a/plugins/WebUi/templates/advanced/part_tb_button.html +++ b/deluge/ui/webui/templates/white/part_tb_button.html @@ -1,17 +1,17 @@ $def with (method, func, title, image='')
        -
        + $if (get_config('button_style') == 0): $if (get_config('button_style') == 1): $if image: - + $else:
        - \ No newline at end of file diff --git a/deluge/ui/webui/templates/white/part_toolbar.html b/deluge/ui/webui/templates/white/part_toolbar.html new file mode 100644 index 000000000..2c8ff9cb2 --- /dev/null +++ b/deluge/ui/webui/templates/white/part_toolbar.html @@ -0,0 +1,6 @@ +$for id, title, image, flag, method, url, important in toolbar_items: + $if important: + diff --git a/deluge/ui/webui/templates/white/part_torrent_list.html b/deluge/ui/webui/templates/white/part_torrent_list.html new file mode 100644 index 000000000..4df6e3583 --- /dev/null +++ b/deluge/ui/webui/templates/white/part_torrent_list.html @@ -0,0 +1,103 @@ +$def with (torrent_list, label_filters) + + + + + + + + + + $:(sort_head('state', 'S')) + $:(sort_head('queue', '#')) + $:(sort_head('name', _('Name'))) + $:(sort_head('total_size', _('Size'))) + $:(sort_head('progress', _('Progress'))) + + $if label_filters: + + $:(sort_head('label', _('Label'))) + $:(sort_head('tracker_host', _('Tracker'))) + + $:(sort_head('num_seeds', _('Seeders'))) + $:(sort_head('num_peers', _('Peers'))) + $:(sort_head('download_payload_rate', _('Download'))) + $:(sort_head('upload_payload_rate', _('Upload'))) + $:(sort_head('eta', _('Eta'))) + $:(sort_head('distributed_copies', _('Ava'))) + $:(sort_head('ratio', _('Ratio'))) + + + +$altrow(True) +$#4-space indentation is mandatory for for-loops in templetor! +$for torrent in torrent_list: + + + + + + + $if label_filters: + + + + + $else: + 0 + + + + + + + +
        +
        + +
        +
        + $if (torrent.queue == -1): + ∞ + $else: + $(torrent.queue + 1) + + $(crop(torrent.name, 30))$fsize(torrent.total_size) +
        +
        + $_(torrent.state) $int(torrent.progress) % +
        +
        +
        $torrent.label$torrent.tracker_host + $if torrent.total_seeds != -1: + $torrent.num_seeds ($torrent.total_seeds) + $else: + 0 + + $if torrent.total_peers != -1: + $torrent.num_peers ($torrent.total_peers) + $if (torrent.download_payload_rate): + $fspeed(torrent.download_payload_rate) + $else: +   + + $if (torrent.upload_payload_rate): + $fspeed(torrent.upload_payload_rate) + $else: +   + $ftime(torrent.eta)$("%.2f" % torrent.distributed_copies)$("%.2f" % torrent.ratio)
        diff --git a/deluge/ui/webui/templates/white/template_style.css b/deluge/ui/webui/templates/white/template_style.css new file mode 100644 index 000000000..05b5189be --- /dev/null +++ b/deluge/ui/webui/templates/white/template_style.css @@ -0,0 +1,331 @@ +$def with (style) +/* +preprocessed style. +avoid copy and pase of colours. +*/ + + +/*global:*/ +body, th, td,tr , div,table , div{ + font-family: Bitstream Vera Sans, verdana, arial, sans-serif; + font-size:12px; + padding:0px; + margin:0px; + border-style: hidden; + border-spacing:0px; +} + +a { + color: #0000AA; + } +a:visited { color: #0000AA;} + +th { + font-weight:normal; + text-align: left; + } + +form { + display:inline; +} + +img{ + border:0; +} + +/*controls:*/ +div.error { + background-color:#FFFFFF; + color:#AA0000; + font-weight:bold; + -moz-border-radius:10px; + width:200px; + margin-bottom:20px; + padding:10px; + +} +div.info { + background-color:#FFFFFF; + color: #0000AA; + font-weight:bold; +} + +a.tab_button_active { + color: #0000AA; + text-decoration:none; + font-weight:bold; + color:#000; +} + +div.deluge_button{ + display:inline; +} + +div.panel { + border-style:solid; + border-width:2px; + border-color:#C3D9FF; + background-color:#FAFAFA; /*offf-topic-hint:allo allo*/ + -moz-border-radius:5px; + width:700px; + margin-left:20px; + margin-top:20px; + +} + +h2 { + background-color:#E0ECFF; + margin:0; +} + +h3 { + background-color:#E0ECFF; + margin:0; +} + + +/*page from top to bottom:*/ + +/*top part :*/ +#admin_toolbar { + text-align:right; + float; +} + +#home_top { + text-align:left; + float; +} + +/*toolbar*/ +#toolbar { + background-color:#E0ECFF; +} + + +#organize_block { + width:170px; + height:300px; + /*border-style:solid; + border-width:2px; + border-color:#B5EDBC; + -moz-border-radius:8px;*/ + float: left; + margin-left: 10px; + margin-top:20px; +} + + +#organize_state div.title { + background-color:#E0ECFF; + margin-right:2px; + text-indent: 10px; +} + +#organize_state ul { + list-style-type: none; + padding: 0; + margin-top:0px; +} + +#organize_state li { + margin-top: 2px; + text-indent: 10px; + height:20px; + +} +#organize_state li:hover { + /*background-color:#68a;*/ +} + +#organize_state li.selected { + background-color:#C3D9FF; + -moz-border-radius:5px 0px 0px 5px; +} + + + + + +/*torrent table*/ + +#torrent_list_block{ + border-style:solid; + border-width:2px 2px 2px 12px; + border-color:#C3D9FF; + -moz-border-radius:5px; + height:280px; + /*float: right;*/ +} + + +XX#torrent_table td { + border-bottom-style:solid; + border-bottom-width:1px; + border-bottom-color:#000000; +} + +#torrent_table th { + background-color:#C3D9FF; +} + +tr.altrow1 { + background-color:#FAFAFA; /*offf-topic-hint:allo allo*/ +} + +th { + padding-left:3px; +} +tr.altrow1 > td { + padding-left:3px; +} +tr.altrow0 > td { + padding-left:3px; +} +tr.torrent_table_selected > td { + padding-left:3px; +} + + +tr.torrent_table_selected { + background-color:#FFFFCC; +} + +div.progress_bar{ + background-color:#E0ECFF; + overflow:visible; + white-space: nowrap; + /*color:blue;*/ + /*-moz-border-radius:5px;*/ /*ff only setting*/ +} + +/*info panel(inner):*/ + +#info_panel_div { + width:100%; + margin-top:20px; + border-style:solid; + /*old-green: + border-width:2 2 0 0; + border-width:2 2 2 12;*/ + /*new-blue:*/ + border-width:2px 2px 2px 12px; + border-color:#C3D9FF; + + + -moz-border-radius:5px; + /*float: right;*/ +} +#torrent_info_tabs { + /*old-green + background-color:#B5EDBC + */ + /*new-blue:*/ + background-color:#E0ECFF; + + +} + +#torrent_info tr.head{ + background-color:#C3D9FF; +} +#torrent_info div.progress_bar{ + background-color:#C3D9FF; +} +#torrent_info div.button_bar{ + background-color:#C3D9FF; +} + + + +td.info_label { + /*width:80px;*/ +} + +#torrent_tab tr.head { + background-color:#74DD82; +} +#torrent_tab tr.altrow0 { + background-color:#FFFFFF; +} + +#torrent_tab a.tab_button { + margin-right:10px; +} +#torrent_tab a.tab_button_active { + margin-right:10px; +} + +/*/torrent/info*/ +#torrent_info #torrent_tab tr.head { + background-color:#74DD82; +} + + + +/*config:*/ +#config_chooser { + margin-left:20px; + float: left; + width:150px; + text-align:left; + height:none; + background-color:#FFFFFF; + border:none; +} + +#config_chooser ul { + list-style-type: none; + padding: 0; + margin-top:0px; +} +#config_chooser h3 { + background-color:#E0ECFF; + margin-right:2px; + text-indent: 10px; + font-size:12px; + font-weight:normal; +} + + +#config_chooser li { + margin-top: 2px; + text-indent: 10px; + height:20px; +} +#config_chooser li.selected { + background-color:#C3D9FF; + -moz-border-radius:5 0 0 5; +} + +#config_panel { + height:none; + float:left; + width:500px; + height:500px; + margin-left:0px; + border-width:2px 2px 2px 12px; +} +#config_panel th { + text-align:right; +} + +/*config:*/ + +/*newforms*/ +ul.errorlist { + display:inline; + float:right; + height:15px; + padding:5px; + margin:0px; + padding-left:10px; +} + +ul.errorlist > li { + background-color:#FFFFFF; + color:#AA0000; + display:inline; + padding:0px; + margin:0px; +} \ No newline at end of file diff --git a/deluge/ui/webui/templates/white/torrent_info_inner.html b/deluge/ui/webui/templates/white/torrent_info_inner.html new file mode 100644 index 000000000..c60e4983e --- /dev/null +++ b/deluge/ui/webui/templates/white/torrent_info_inner.html @@ -0,0 +1,22 @@ +$def with (torrent, active_tab) + + + + Deluge:$torrent.name + + + + +
        +$for id, title, tab in detail_tabs: + $:render.part_tab_button(id, title, active_tab) +
        + +
        +$for id, title, tab in detail_tabs: + $if active_tab == id: + $:render[tab](torrent) +
        + + + diff --git a/deluge/ui/webui/templates/white/torrent_label.html b/deluge/ui/webui/templates/white/torrent_label.html new file mode 100644 index 000000000..f17404c2f --- /dev/null +++ b/deluge/ui/webui/templates/white/torrent_label.html @@ -0,0 +1,29 @@ +$def with (torrent_ids, torrent_list, labels) +$:render.header(_("Label torrent")) +
        +
        +
        + +

        $_("Label torrent")

        +
          +$for torrent in torrent_list: +
        • $torrent.name ($torrent.label)
        • +
        + +
        + + +
        +
        + + +
        +
        +
        +
        +$:render.footer() \ No newline at end of file diff --git a/deluge/ui/webui/tests/multicall_notepad.py b/deluge/ui/webui/tests/multicall_notepad.py new file mode 100644 index 000000000..4781e5d3f --- /dev/null +++ b/deluge/ui/webui/tests/multicall_notepad.py @@ -0,0 +1,102 @@ +""" +test multicall. +""" +import time + +from WebUi.webserver_common import ws, proxy, async_proxy +ws.init_06() + +TORRENT_KEYS = ['name', 'total_size', 'num_files', 'num_pieces', 'piece_length', + 'eta', 'ratio', 'file_progress', 'distributed_copies', 'total_done', + 'total_uploaded', 'state', 'paused', 'progress', 'next_announce', + 'total_payload_download', 'total_payload_upload', 'download_payload_rate', + 'upload_payload_rate', 'num_peers', 'num_seeds', 'total_peers', 'total_seeds', + 'total_wanted', 'tracker', 'trackers', 'tracker_status', 'save_path', + 'files', 'file_priorities', 'compact', 'max_connections', + 'max_upload_slots', 'max_download_speed', 'prioritize_first_last', 'private' + ] + +if False: + # + #A: translate this into 1 multicall: + + start = time.time() + stats = { + 'download_rate':proxy.get_download_rate(), + 'upload_rate':proxy.get_upload_rate(), + 'max_download':proxy.get_config_value('max_download_speed'), + 'max_upload':proxy.get_config_value('max_upload_speed'), + 'num_connections':proxy.get_num_connections(), + 'max_num_connections':proxy.get_config_value('max_connections_global') + } + + print "sync-stats:",time.time() - start + + print stats + + # + #map callback to a a dict-setter + def dict_cb(key,d): + def callback(result): + d[key] = result + return callback + + start = time.time() + d = {} + async_proxy.get_download_rate(dict_cb('download_rate',d)) + async_proxy.get_upload_rate(dict_cb('upload_rate',d)) + async_proxy.get_config_value(dict_cb('max_download',d),"max_download_speed") + async_proxy.get_config_value(dict_cb('max_upload',d),"max_upload_speed") + async_proxy.get_num_connections(dict_cb("num_connections",d)) + async_proxy.get_config_value(dict_cb('max_num_connections',d),"max_connections_global") + + async_proxy.force_call(block=True) + + print "Async-stats:",time.time() - start + print d + + # + #B: translate this to multicall: + # + + #old-sync: + start = time.time() + + torrent_list = [proxy.get_torrent_status(id, TORRENT_KEYS ) + for id in proxy.get_session_state() + ] + + print "sync-list:",time.time() - start + print torrent_list[0] + + #new async: + """ + torrent.compact, + torrent.max_connections, + torrent.max_upload_slots, + torrent.max_upload_speed, + torrent.max_download_speed, + torrent.prioritize_first_last, + torrent.private + """ + + + start = time.time() + + torrent_ids = proxy.get_session_state() #Syc-api. + torrent_dict = {} + for id in torrent_ids: + async_proxy.get_torrent_status(dict_cb(id,torrent_dict), id, TORRENT_KEYS ) + async_proxy.force_call(block=True) + + print "Async-list:",time.time() - start + print "\n".join(torrent_dict[torrent_ids[0]].keys()) + print torrent_dict[torrent_ids[0]] + +if False: + print proxy.get_config_value('download_location') + +if True: + torrent_id = proxy.get_session_state()[0] + print torrent_id + proxy.move_torrent([torrent_id],"/media/sdb1/test") \ No newline at end of file diff --git a/plugins/WebUi/tests/test_all.py b/deluge/ui/webui/tests/test_all.py similarity index 90% rename from plugins/WebUi/tests/test_all.py rename to deluge/ui/webui/tests/test_all.py index f6c750fea..c9f6127ab 100644 --- a/plugins/WebUi/tests/test_all.py +++ b/deluge/ui/webui/tests/test_all.py @@ -6,21 +6,18 @@ unittest the right way feels so unpythonic :( """ import unittest import cookielib, urllib2 , urllib -import WebUi.webserver_common as ws +from WebUi.webserver_common import ws,TORRENT_KEYS, proxy import operator - -ws.init_05() -print 'test-env=',ws.ENV - - +ws.init_06() +print 'test-env=',ws.env #CONFIG: BASE_URL = 'http://localhost:8112' PWD = 'deluge' def get_status(id): - return ws.proxy.get_torrent_status(id,ws.TORRENT_KEYS) + return proxy.get_torrent_status(id,TORRENT_KEYS) #BASE: #303 = see other @@ -97,7 +94,7 @@ class TestWebUiBase(unittest.TestCase): else: pass - first_torrent_id = property(lambda self: ws.proxy.get_session_state()[0]) + first_torrent_id = property(lambda self: proxy.get_session_state()[0]) first_torrent = property(lambda self: get_status(self.first_torrent_id)) @@ -107,7 +104,7 @@ class TestNoAuth(TestWebUiBase): self.assert_303('','/login') self.assert_303('/index','/login') #self.assert_303('/torrent/pause/','/login') - self.assert_303('/config','/login') + #self.assert_303('/config','/login') self.assert_303('/torrent/info/','/login') def test404(self): @@ -141,7 +138,7 @@ class TestSession(TestWebUiBase): #there are no sort-coockies yet so the default page is /index. self.assert_303('/home','/index') self.assert_exists('/index') - self.assert_exists('/config') + #self.assert_exists('/config') self.assert_exists('/torrent/add') self.assert_303('/','/index') self.assert_303('','/index') @@ -203,17 +200,17 @@ class TestIntegration(TestWebUiBase): 'http://torrents.aelitis.com:88/torrents/azautoseeder_0.1.1.jar.torrent' ]) - torrent_ids = ws.proxy.get_session_state() + torrent_ids = proxy.get_session_state() #avoid hammering, investigate current torrent-list and do not re-add. #correct means : 3 torrent's in list (for now) if len(torrent_ids) <> 3: #delete all, nice use case for refactoring delete.. - torrent_ids = ws.proxy.get_session_state() + torrent_ids = proxy.get_session_state() for torrent in torrent_ids: - ws.proxy.remove_torrent([torrent], False, False) + proxy.remove_torrent([torrent], False, False) - torrent_ids = ws.proxy.get_session_state() + torrent_ids = proxy.get_session_state() self.assertEqual(torrent_ids, []) #add 3 using url. @@ -221,30 +218,27 @@ class TestIntegration(TestWebUiBase): self.assert_303('/torrent/add','/index',{'url':url,'torrent':None}) #added? - self.torrent_ids = ws.proxy.get_session_state() + self.torrent_ids = proxy.get_session_state() self.assertEqual(len(self.torrent_ids), 3) else: - #test correctness of existing-list - #The setup makes 0.6 fail everything, added an else.. - for url in self.urls: - if ws.ENV.startswith('0.5'): + if ws.env <> '0.6': + #test correctness of existing-list + for url in self.urls: self.assert_500('/torrent/add',{'url':url,'torrent':None}) - else: - self.assert_303('/torrent/add','/index',{'url':url,'torrent':None}) def testPauseResume(self): #pause all self.assert_303('/pause_all','/index', post=1) #pause worked? - pause_status = [get_status(id)["user_paused"] for id in ws.proxy.get_session_state()] + pause_status = [get_status(id)["user_paused"] for id in proxy.get_session_state()] for paused in pause_status: self.assertEqual(paused, True) #resume all self.assert_303('/resume_all','/index', post=1) #resume worked? - pause_status = [get_status(id)["user_paused"] for id in ws.proxy.get_session_state()] + pause_status = [get_status(id)["user_paused"] for id in proxy.get_session_state()] for paused in pause_status: self.assertEqual(paused,False) #pause again. @@ -260,7 +254,7 @@ class TestIntegration(TestWebUiBase): def testQueue(self): #find last: - torrent_id = [id for id in ws.proxy.get_session_state() + torrent_id = [id for id in proxy.get_session_state() if (get_status(id)['queue_pos'] ==3 )][0] #queue @@ -291,7 +285,7 @@ class TestIntegration(TestWebUiBase): def testMeta(self): #info available? - for torrent_id in ws.proxy.get_session_state(): + for torrent_id in proxy.get_session_state(): self.assert_exists('/torrent/info/%s' % torrent_id) self.assert_exists('/torrent/delete/%s' % torrent_id) @@ -360,9 +354,26 @@ class TestIntegration(TestWebUiBase): ,'/torrent/info/' + torrent_id, post = 1) """ + def testConfig(self): + #0.6 only + if ws.env <> '0.6': + return + # + import WebUi.config_tabs_webui #auto registers + import WebUi.config_tabs_deluge #auto registers + import WebUi.config as config + + for name in config.blocks: + self.assert_exists("/config/%s" % name) + + #todo->post page with current values. + + + + + -# if False: suiteFew = unittest.TestSuite() @@ -376,7 +387,6 @@ elif False: suiteFew.addTest(TestIntegration("testDoRedirect")) unittest.TextTestRunner(verbosity=2).run(suiteFew) - else: unittest.main() diff --git a/deluge/ui/webui/torrent_add.py b/deluge/ui/webui/torrent_add.py new file mode 100644 index 000000000..20dfdfadc --- /dev/null +++ b/deluge/ui/webui/torrent_add.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) Martijn Voncken 2008 +# +# 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 2, 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 deluge.ui.client import sclient as proxy +from deluge.log import LOG as log +from deluge import component + +import utils +from render import render, error_page +import page_decorators as deco +import lib.newforms_plus as forms +import web + +class OptionsForm(forms.Form): + download_location = forms.ServerFolder(_("Download Location")) + compact_allocation = forms.CheckBox(_("Compact Allocation")) + + #download + max_download_speed_per_torrent = forms.DelugeFloat( + _("Maximum Down Speed")) + max_upload_speed_per_torrent = forms.DelugeFloat( + _("Maximum Up Speed")) + max_connections_per_torrent = forms.DelugeInt(_("Maximum Connections")) + max_upload_slots_per_torrent = forms.DelugeInt(_("Maximum Upload Slots")) + #general + prioritize_first_last_pieces = forms.CheckBox( + _('Prioritize first and last pieces')) + add_paused = forms.CheckBox(_('Add In Paused State')) + default_private = forms.CheckBox(_('Set Private Flag')) + + def initial_data(self): + data = proxy.get_config() + log.debug("add:Init options with:%s" % data) + return data + +class AddForm(forms.Form): + url = forms.CharField(label=_("Url"), required=False, + widget=forms.TextInput(attrs={'size':60})) + torrent = forms.CharField(label=_("Upload torrent"), required=False, + widget=forms.FileInput(attrs={'size':60})) + #hash = forms.CharField(label=_("Hash"), required=False, + # widget=forms.TextInput(attrs={'size':60})) + #ret = forms.CheckBox(_('Add more')) + + choose_files = forms.CheckBox(_('Choose Files')) + + +class torrent_add: + + def add_page(self,error = None): + vars = web.input(url = None) + form_data = {'url':vars.url} + + options_data = None + if error: + options_data = utils.get_newforms_data(OptionsForm) + log.debug("add:(error-state):Init options with:%s" % options_data) + return render.torrent_add(AddForm(form_data),OptionsForm(options_data), error) + + @deco.deluge_page + def GET(self, name): + return self.add_page() + + + @deco.check_session + def POST(self, name): + """ + allows: + *posting of url + *posting file-upload + """ + vars = web.input(url = None, torrent = {},choose_files = False) + + options_form = OptionsForm(utils.get_newforms_data(OptionsForm)) + if not options_form.is_valid(): + print self.add_page(error = _("Error in torrent options.")) + return + options = options_form.cleaned_data + + + + torrent_name = None + torrent_data = None + if vars.torrent.filename: + torrent_name = vars.torrent.filename + torrent_data = vars.torrent.file.read() + + if vars.url and torrent_name: + #error_page(_("Choose an url or a torrent, not both.")) + print self.add_page(error = _("Choose an url or a torrent, not both.")) + return + + if vars.url: + proxy.add_torrent_url(vars.url, None,options) + log.debug("add-url:options :%s" % options) + self.redirect(vars.choose_files) + elif torrent_name: + proxy.add_torrent_file_binary(vars.torrent.filename, torrent_data, options) + log.debug("add-file:options :%s" % options) + self.redirect(vars.choose_files) + else: + print self.add_page(error = _("No data")) + return + + def redirect(self,choose_files): + if choose_files: #redirect to file chooser + torrent_id = proxy.get_session_state()[-1] #HACK! no return-value for torrent_add_* + utils.seeother("/torrent/files/%s" % torrent_id) + + else: #default + utils.do_redirect() + + +def register(): + component.get("PageManager").register_page("/torrent/add(.*)",torrent_add) \ No newline at end of file diff --git a/deluge/ui/webui/torrent_move.py b/deluge/ui/webui/torrent_move.py new file mode 100644 index 000000000..5c321adbd --- /dev/null +++ b/deluge/ui/webui/torrent_move.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) Martijn Voncken 2008 +# +# 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 2, 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 deluge.ui.client import sclient as proxy +from deluge.log import LOG as log +from deluge import component + +import utils +from render import render +import page_decorators as deco +import lib.newforms_plus as forms + +#Too much boilerplate code here, todo : fix it. + +class MoveForm(forms.Form): + save_path = forms.ServerFolder(_("Move To")) + def initial_data(self): + return {'save_path':proxy.get_config_value('download_location')} + +class torrent_move: + + def move_page(self, name, error = None): + torrent_ids = name.split(',') + torrent_list = [utils.get_torrent_status(id) for id in torrent_ids] + + data = None + if error: + data = utils.get_newforms_data(MoveForm) + + form = MoveForm(data) + + return render.torrent_move(name, torrent_list , form, error) + + @deco.deluge_page + def GET(self, name): + return self.move_page(name) + + @deco.check_session + def POST(self, name): + torrent_ids = name.split(',') + form = MoveForm(utils.get_newforms_data(MoveForm)) + if not form.is_valid(): + print self.move_page(name, error = _("Error in Path.")) + return + save_path = form.cleaned_data["save_path"] + proxy.move_storage(torrent_ids, save_path) + utils.do_redirect() + +def register(): + component.get("PageManager").register_page("/torrent/move/(.*)",torrent_move) diff --git a/deluge/ui/webui/torrent_options.py b/deluge/ui/webui/torrent_options.py new file mode 100644 index 000000000..94934b8b5 --- /dev/null +++ b/deluge/ui/webui/torrent_options.py @@ -0,0 +1,56 @@ +# Copyright (C) Martijn Voncken 2008 +# License: GPL v2(+OpenSSL exception), see LICENSE file in base directory. + +from deluge.ui.client import sclient, aclient +from deluge.log import LOG as log +from deluge import component + +import page_decorators as deco +import lib.newforms_plus as forms +from render import error_page +import utils + +class TorrentOptionsForm(forms.Form): + #download + max_download_speed = forms.DelugeFloat( + _("Maximum Down Speed")) + max_upload_speed = forms.DelugeFloat( + _("Maximum Up Speed")) + max_connections = forms.DelugeInt(_("Maximum Connections")) + max_upload_slots = forms.DelugeInt(_("Maximum Upload Slots")) + #general + prioritize_first_last = forms.CheckBox( + _('Prioritize first and last pieces [TODO!]')) + #private = forms.CheckBox(_('Private')) + +class torrent_options: + @deco.check_session + @deco.torrent + def POST(self, torrent): + options_form = TorrentOptionsForm(utils.get_newforms_data(TorrentOptionsForm)) + if not options_form.is_valid(): + #!!!!!!!!!!!!! + #todo:user-friendly error-handling. + #!!!!!!!! + return error_page(_("Error in torrent options.")) + options = options_form.cleaned_data + + + #options['prioritize_first_last'] + aclient.set_torrent_max_connections(torrent.id, options['max_connections']) + aclient.set_torrent_max_download_speed(torrent.id, options['max_download_speed']) + aclient.set_torrent_max_upload_slots(torrent.id, options['max_upload_slots']) + aclient.set_torrent_max_upload_speed(torrent.id, options['max_upload_speed']) + #aclient.set_torrent_private_flag(torrent.id, options['private']) + + aclient.force_call() + + utils.do_redirect() + + + + +def register(): + from render import template + template.Template.globals["forms"].torrent_options = lambda torrent : TorrentOptionsForm(torrent) + component.get("PageManager").register_page("/torrent/options/(.*)", torrent_options) diff --git a/deluge/ui/webui/utils.py b/deluge/ui/webui/utils.py new file mode 100644 index 000000000..0a2096948 --- /dev/null +++ b/deluge/ui/webui/utils.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +# +# webserver_framework.py +# +# Copyright (C) Martijn Voncken 2007 +# +# 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 2, 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. + +import os +import traceback +import random +from operator import attrgetter +import datetime +import pickle +from urlparse import urlparse +from md5 import md5 + +import web +from web import changequery , template , url , Storage +from web import cookies, setcookie as w_setcookie +from web import seeother as w_seeother + +from deluge.common import fsize, fspeed, ftime +from deluge import component +from deluge.log import LOG as log +from deluge.configmanager import ConfigManager + +from webserver_common import TORRENT_KEYS, CONFIG_DEFAULTS +from deluge.ui.client import sclient, aclient + +webui_plugin_manager = component.get("WebPluginManager") +config = ConfigManager("webui06.conf") + +#async-proxy: map callback to a a dict-setter +def dict_cb(key,d): + def callback(result): + d[key] = result + return callback + +#methods: +def setcookie(key, val): + """add 30 days expires header for persistent cookies""" + return w_setcookie(key, val , expires=2592000) + +#really simple sessions, to bad i had to implement them myself. +SESSIONS = [] +def start_session(): + session_id = str(random.random()) + SESSIONS.append(session_id) + setcookie("session_id", session_id) + +def end_session(): + session_id = getcookie("session_id") + setcookie("session_id","") +#/sessions + +def seeother(url, *args, **kwargs): + url_with_base = config["base"] + url + log.debug("seeother:%s" % url_with_base) + return w_seeother(url_with_base, *args, **kwargs) + +def self_url(**kwargs): + return config["base"] + changequery(**kwargs) + +def do_redirect(): + """go to /index unless the redir var is set.""" + vars = web.input(redir=None) + if vars.redir: + w_seeother(vars.redir) #redir variable contains base + return + #default: + seeother('/index') + +def getcookie(key, default = None): + "because i'm too lazy to type 3 lines for something this simple" + key = str(key).strip() + ck = cookies() + return ck.get(key, default) + +def get_stats(): + stats = Storage() + + aclient.get_download_rate(dict_cb('download_rate',stats)) + aclient.get_upload_rate(dict_cb('upload_rate',stats)) + aclient.get_config_value(dict_cb('max_download',stats) + ,"max_download_speed") + aclient.get_config_value(dict_cb('max_upload',stats) + ,"max_upload_speed") + aclient.get_num_connections(dict_cb("num_connections",stats)) + aclient.get_config_value(dict_cb('max_num_connections',stats) + ,"max_connections_global") + aclient.get_dht_nodes(dict_cb('dht_nodes',stats)) + + aclient.force_call(block=True) + + stats.download_rate = fspeed(stats.download_rate) + stats.upload_rate = fspeed(stats.upload_rate) + + if stats.max_upload < 0: + stats.max_upload = _("∞") + else: + stats.max_upload = "%s KiB/s" % stats.max_upload + + if stats.max_download < 0: + stats.max_download = _("∞") + else: + stats.max_download = "%s KiB/s" % stats.max_download + + return stats + +def enhance_torrent_status(torrent_id,status): + """ + in: raw torrent_status + out: enhanced torrent_staus + """ + status = Storage(status) + + if status.tracker == 0: + #0.6 does not raise a decent error on non-existing torrent. + raise UnknownTorrentError(torrent_id) + + status.id = torrent_id + + #action for torrent_pause + if status.state == "Paused": + status.action = "start" + else: + status.action = "stop" + + return status + +def get_torrent_status(torrent_id): + """ + helper method. + enhance sclient.get_torrent_status with some extra data + """ + status = sclient.get_torrent_status(torrent_id,TORRENT_KEYS) + return enhance_torrent_status(torrent_id, status) + +def get_enhanced_torrent_list(torrent_ids): + """ + returns a list of storified-torrent-dicts. + """ + torrent_dict = sclient.get_torrents_status(torrent_ids, TORRENT_KEYS) + return [enhance_torrent_status(id, status) + for id, status in torrent_dict.iteritems()] + +def get_newforms_data(form_class): + """ + glue for using web.py and newforms. + returns a dict with name/value of the post-data. + """ + import lib.newforms_plus as forms + fields = form_class.base_fields.keys() + form_data = {} + vars = web.input() + for field in fields: + form_data[field] = vars.get(field) + #log.debug("form-field:%s=%s" % (field, form_data[field])) + #DIRTY HACK: (for multiple-select) + if isinstance(form_class.base_fields[field], + forms.MultipleChoiceField): + form_data[field] = web.input(**{field:[]})[field] + #/DIRTY HACK + return form_data + +#/utils + +#daemon: +def daemon_test_online_status(uri): + """Tests the status of URI.. Returns True or False depending on status. + """ + online = True + host = None + try: + host = xmlrpclib.ServerProxy(uri) + host.ping() + except socket.error: + online = False + + del host + self.online_status[uri] = online + return online + +def daemon_start_localhost(port): + """Starts a localhost daemon""" + port = str(port) + log.info("Starting localhost:%s daemon..", port) + # Spawn a local daemon + os.popen("deluged -p %s" % port) + +def daemon_connect(uri): + if config.get('daemon') <> uri: + config.set('daemon', uri) + config.save() + + sclient.set_core_uri(uri) + webui_plugin_manager.start() + +#generic: +def logcall(func): + "deco to log a function/method-call" + def deco(*args, **kwargs): + log.debug("call: %s<%s,%s>" % (func.__name__, args, kwargs)) + return func(*args, **kwargs) #logdeco + + return deco + +#c&p from ws: +def update_pwd(pwd): + sm = md5() + sm.update(str(random.getrandbits(5000))) + salt = sm.digest() + m = md5() + m.update(salt) + m.update(pwd) + # + config.set("pwd_salt", salt) + config.set("pwd_md5", m.digest()) + config.save() + +def check_pwd(pwd): + m = md5() + m.update(config.get('pwd_salt')) + m.update(pwd) + return (m.digest() == config.get('pwd_md5')) + +def set_config_defaults(): + changed = False + for key, value in CONFIG_DEFAULTS.iteritems(): + if not key in config.config: + config.config[key] = value + changed = True + + from render import render + if not config.get("template") in render.get_templates(): + config.set("template", CONFIG_DEFAULTS["template"]) + changed = True + + if changed: + config.save() + +def apply_config(): + #etc, mostly for apache: + from render import render + try: + #sclient.set_core_uri(config.get('daemon')) + daemon_connect(config.get('daemon')) + except Exception,e: + log.debug("error setting core uri:%s:%s:%s" % (config.get('daemon'),e,e.message)) + render.set_global('base', config.get('base')) + render.apply_cfg() + +#exceptions: +class WebUiError(Exception): + """the message of these exceptions will be rendered in + render.error(e.message) in debugerror.py""" + pass + +class UnknownTorrentError(WebUiError): + pass + diff --git a/deluge/ui/webui/version b/deluge/ui/webui/version new file mode 100644 index 000000000..725a5ba2a --- /dev/null +++ b/deluge/ui/webui/version @@ -0,0 +1 @@ +185 diff --git a/deluge/ui/webui/web.py b/deluge/ui/webui/web.py new file mode 100644 index 000000000..6217a1dbb --- /dev/null +++ b/deluge/ui/webui/web.py @@ -0,0 +1,2 @@ +#compatibility: use the included version/release of web.py. +from lib.web import * diff --git a/src/__init__.py b/deluge/ui/webui/webserver_common.py similarity index 52% rename from src/__init__.py rename to deluge/ui/webui/webserver_common.py index 84c06fb4d..30a756d1a 100644 --- a/src/__init__.py +++ b/deluge/ui/webui/webserver_common.py @@ -1,19 +1,18 @@ +#!/usr/bin/env python # -*- coding: utf-8 -*- # -# __init__.py -# -# Copyright (C) Marcos Pinto 2007 +# Copyright (C) Martijn Voncken 2007 # # 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 2, 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., @@ -30,25 +29,36 @@ # 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 gettext -import pygtk -pygtk.require('2.0') -import gtk.glade -import locale +""" +webui constants +""" import os -import common -APP = 'deluge' -DIR = os.path.join(common.INSTALL_PREFIX, 'share', 'locale') -try: - locale.setlocale(locale.LC_ALL, '') -except: - try: - locale.setlocale(locale.LC_MESSAGES, '') - except: - pass -gtk.glade.bindtextdomain(APP, DIR) -gtk.glade.textdomain(APP) -gettext.bindtextdomain(APP, DIR) -gettext.textdomain(APP) -gettext.install(APP, DIR, unicode=1) + +TORRENT_KEYS = ['name', 'total_size', 'num_files', 'num_pieces', 'piece_length', + 'eta', 'ratio', 'file_progress', 'distributed_copies', 'total_done', + 'total_uploaded', 'state', 'paused', 'progress', 'next_announce', + 'total_payload_download', 'total_payload_upload', 'download_payload_rate', + 'upload_payload_rate', 'num_peers', 'num_seeds', 'total_peers', 'total_seeds', + 'total_wanted', 'tracker', 'trackers', 'tracker_status', 'save_path', + 'files', 'file_priorities', 'compact', 'max_connections', + 'max_upload_slots', 'max_download_speed', 'prioritize_first_last', + 'private','max_upload_speed','queue','peers', + #builtin plugins: + 'tracker_name', #organize-plugin + 'tracker_host', 'label' #label-plugin + ] + +CONFIG_DEFAULTS = { + "port":8112, + "button_style":2, + "auto_refresh":False, + "auto_refresh_secs": 10, + "template":"white", + "pwd_salt":"2\xe8\xc7\xa6(n\x81_\x8f\xfc\xdf\x8b\xd1\x1e\xd5\x90", + "pwd_md5":".\xe8w\\+\xec\xdb\xf2id4F\xdb\rUc", + "cache_templates":True, + "daemon":"http://localhost:58846", + "base":"", + "disallow":{} +} diff --git a/deluge/ui/webui/webui.py b/deluge/ui/webui/webui.py new file mode 100644 index 000000000..d414015df --- /dev/null +++ b/deluge/ui/webui/webui.py @@ -0,0 +1,38 @@ +# +# webui.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# 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 2 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. + +class WebUI: + def __init__(self, args): + import deluge_webserver + deluge_webserver.run(debug = False) + diff --git a/deluge/xmlrpclib.py b/deluge/xmlrpclib.py new file mode 100644 index 000000000..3871c7f73 --- /dev/null +++ b/deluge/xmlrpclib.py @@ -0,0 +1,1491 @@ +# +# XML-RPC CLIENT LIBRARY +# $Id: xmlrpclib.py 41594 2005-12-04 19:11:17Z andrew.kuchling $ +# +# an XML-RPC client interface for Python. +# +# the marshalling and response parser code can also be used to +# implement XML-RPC servers. +# +# Notes: +# this version is designed to work with Python 2.1 or newer. +# +# History: +# 1999-01-14 fl Created +# 1999-01-15 fl Changed dateTime to use localtime +# 1999-01-16 fl Added Binary/base64 element, default to RPC2 service +# 1999-01-19 fl Fixed array data element (from Skip Montanaro) +# 1999-01-21 fl Fixed dateTime constructor, etc. +# 1999-02-02 fl Added fault handling, handle empty sequences, etc. +# 1999-02-10 fl Fixed problem with empty responses (from Skip Montanaro) +# 1999-06-20 fl Speed improvements, pluggable parsers/transports (0.9.8) +# 2000-11-28 fl Changed boolean to check the truth value of its argument +# 2001-02-24 fl Added encoding/Unicode/SafeTransport patches +# 2001-02-26 fl Added compare support to wrappers (0.9.9/1.0b1) +# 2001-03-28 fl Make sure response tuple is a singleton +# 2001-03-29 fl Don't require empty params element (from Nicholas Riley) +# 2001-06-10 fl Folded in _xmlrpclib accelerator support (1.0b2) +# 2001-08-20 fl Base xmlrpclib.Error on built-in Exception (from Paul Prescod) +# 2001-09-03 fl Allow Transport subclass to override getparser +# 2001-09-10 fl Lazy import of urllib, cgi, xmllib (20x import speedup) +# 2001-10-01 fl Remove containers from memo cache when done with them +# 2001-10-01 fl Use faster escape method (80% dumps speedup) +# 2001-10-02 fl More dumps microtuning +# 2001-10-04 fl Make sure import expat gets a parser (from Guido van Rossum) +# 2001-10-10 sm Allow long ints to be passed as ints if they don't overflow +# 2001-10-17 sm Test for int and long overflow (allows use on 64-bit systems) +# 2001-11-12 fl Use repr() to marshal doubles (from Paul Felix) +# 2002-03-17 fl Avoid buffered read when possible (from James Rucker) +# 2002-04-07 fl Added pythondoc comments +# 2002-04-16 fl Added __str__ methods to datetime/binary wrappers +# 2002-05-15 fl Added error constants (from Andrew Kuchling) +# 2002-06-27 fl Merged with Python CVS version +# 2002-10-22 fl Added basic authentication (based on code from Phillip Eby) +# 2003-01-22 sm Add support for the bool type +# 2003-02-27 gvr Remove apply calls +# 2003-04-24 sm Use cStringIO if available +# 2003-04-25 ak Add support for nil +# 2003-06-15 gn Add support for time.struct_time +# 2003-07-12 gp Correct marshalling of Faults +# 2003-10-31 mvl Add multicall support +# 2004-08-20 mvl Bump minimum supported Python version to 2.1 +# +# Copyright (c) 1999-2002 by Secret Labs AB. +# Copyright (c) 1999-2002 by Fredrik Lundh. +# +# info@pythonware.com +# http://www.pythonware.com +# +# -------------------------------------------------------------------- +# The XML-RPC client interface is +# +# Copyright (c) 1999-2002 by Secret Labs AB +# Copyright (c) 1999-2002 by Fredrik Lundh +# +# By obtaining, using, and/or copying this software and/or its +# associated documentation, you agree that you have read, understood, +# and will comply with the following terms and conditions: +# +# Permission to use, copy, modify, and distribute this software and +# its associated documentation for any purpose and without fee is +# hereby granted, provided that the above copyright notice appears in +# all copies, and that both that copyright notice and this permission +# notice appear in supporting documentation, and that the name of +# Secret Labs AB or the author not be used in advertising or publicity +# pertaining to distribution of the software without specific, written +# prior permission. +# +# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD +# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- +# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR +# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# -------------------------------------------------------------------- + +# +# things to look into some day: + +# TODO: sort out True/False/boolean issues for Python 2.3 + +""" +An XML-RPC client interface for Python. + +The marshalling and response parser code can also be used to +implement XML-RPC servers. + +Exported exceptions: + + Error Base class for client errors + ProtocolError Indicates an HTTP protocol error + ResponseError Indicates a broken response package + Fault Indicates an XML-RPC fault package + +Exported classes: + + ServerProxy Represents a logical connection to an XML-RPC server + + MultiCall Executor of boxcared xmlrpc requests + Boolean boolean wrapper to generate a "boolean" XML-RPC value + DateTime dateTime wrapper for an ISO 8601 string or time tuple or + localtime integer value to generate a "dateTime.iso8601" + XML-RPC value + Binary binary data wrapper + + SlowParser Slow but safe standard parser (based on xmllib) + Marshaller Generate an XML-RPC params chunk from a Python data structure + Unmarshaller Unmarshal an XML-RPC response from incoming XML event message + Transport Handles an HTTP transaction to an XML-RPC server + SafeTransport Handles an HTTPS transaction to an XML-RPC server + +Exported constants: + + True + False + +Exported functions: + + boolean Convert any Python value to an XML-RPC boolean + getparser Create instance of the fastest available parser & attach + to an unmarshalling object + dumps Convert an argument tuple or a Fault instance to an XML-RPC + request (or response, if the methodresponse option is used). + loads Convert an XML-RPC packet to unmarshalled data plus a method + name (None if not present). +""" + +import re, string, time, operator + +from types import * + +# -------------------------------------------------------------------- +# Internal stuff + +try: + unicode +except NameError: + unicode = None # unicode support not available + +try: + import datetime +except ImportError: + datetime = None + +try: + _bool_is_builtin = False.__class__.__name__ == "bool" +except NameError: + _bool_is_builtin = 0 + +def _decode(data, encoding, is8bit=re.compile("[\x80-\xff]").search): + # decode non-ascii string (if possible) + if unicode and encoding and is8bit(data): + data = unicode(data, encoding) + return data + +def escape(s, replace=string.replace): + s = replace(s, "&", "&") + s = replace(s, "<", "<") + return replace(s, ">", ">",) + +if unicode: + def _stringify(string): + # convert to 7-bit ascii if possible + try: + return string.encode("ascii") + except UnicodeError: + return string +else: + def _stringify(string): + return string + +__version__ = "1.0.1" + +# xmlrpc integer limits +MAXINT = 2L**31-1 +MININT = -2L**31 + +# -------------------------------------------------------------------- +# Error constants (from Dan Libby's specification at +# http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php) + +# Ranges of errors +PARSE_ERROR = -32700 +SERVER_ERROR = -32600 +APPLICATION_ERROR = -32500 +SYSTEM_ERROR = -32400 +TRANSPORT_ERROR = -32300 + +# Specific errors +NOT_WELLFORMED_ERROR = -32700 +UNSUPPORTED_ENCODING = -32701 +INVALID_ENCODING_CHAR = -32702 +INVALID_XMLRPC = -32600 +METHOD_NOT_FOUND = -32601 +INVALID_METHOD_PARAMS = -32602 +INTERNAL_ERROR = -32603 + +# -------------------------------------------------------------------- +# Exceptions + +## +# Base class for all kinds of client-side errors. + +class Error(Exception): + """Base class for client errors.""" + def __str__(self): + return repr(self) + +## +# Indicates an HTTP-level protocol error. This is raised by the HTTP +# transport layer, if the server returns an error code other than 200 +# (OK). +# +# @param url The target URL. +# @param errcode The HTTP error code. +# @param errmsg The HTTP error message. +# @param headers The HTTP header dictionary. + +class ProtocolError(Error): + """Indicates an HTTP protocol error.""" + def __init__(self, url, errcode, errmsg, headers): + Error.__init__(self) + self.url = url + self.errcode = errcode + self.errmsg = errmsg + self.headers = headers + def __repr__(self): + return ( + "" % + (self.url, self.errcode, self.errmsg) + ) + +## +# Indicates a broken XML-RPC response package. This exception is +# raised by the unmarshalling layer, if the XML-RPC response is +# malformed. + +class ResponseError(Error): + """Indicates a broken response package.""" + pass + +## +# Indicates an XML-RPC fault response package. This exception is +# raised by the unmarshalling layer, if the XML-RPC response contains +# a fault string. This exception can also used as a class, to +# generate a fault XML-RPC message. +# +# @param faultCode The XML-RPC fault code. +# @param faultString The XML-RPC fault string. + +class Fault(Error): + """Indicates an XML-RPC fault package.""" + def __init__(self, faultCode, faultString, **extra): + Error.__init__(self) + self.faultCode = faultCode + self.faultString = faultString + def __repr__(self): + return ( + "" % + (self.faultCode, repr(self.faultString)) + ) + +# -------------------------------------------------------------------- +# Special values + +## +# Wrapper for XML-RPC boolean values. Use the xmlrpclib.True and +# xmlrpclib.False constants, or the xmlrpclib.boolean() function, to +# generate boolean XML-RPC values. +# +# @param value A boolean value. Any true value is interpreted as True, +# all other values are interpreted as False. + +if _bool_is_builtin: + boolean = Boolean = bool + # to avoid breaking code which references xmlrpclib.{True,False} + True, False = True, False +else: + class Boolean: + """Boolean-value wrapper. + + Use True or False to generate a "boolean" XML-RPC value. + """ + + def __init__(self, value = 0): + self.value = operator.truth(value) + + def encode(self, out): + out.write("%d\n" % self.value) + + def __cmp__(self, other): + if isinstance(other, Boolean): + other = other.value + return cmp(self.value, other) + + def __repr__(self): + if self.value: + return "" % id(self) + else: + return "" % id(self) + + def __int__(self): + return self.value + + def __nonzero__(self): + return self.value + + True, False = Boolean(1), Boolean(0) + + ## + # Map true or false value to XML-RPC boolean values. + # + # @def boolean(value) + # @param value A boolean value. Any true value is mapped to True, + # all other values are mapped to False. + # @return xmlrpclib.True or xmlrpclib.False. + # @see Boolean + # @see True + # @see False + + def boolean(value, _truefalse=(False, True)): + """Convert any Python value to XML-RPC 'boolean'.""" + return _truefalse[operator.truth(value)] + +## +# Wrapper for XML-RPC DateTime values. This converts a time value to +# the format used by XML-RPC. +#

        +# The value can be given as a string in the format +# "yyyymmddThh:mm:ss", as a 9-item time tuple (as returned by +# time.localtime()), or an integer value (as returned by time.time()). +# The wrapper uses time.localtime() to convert an integer to a time +# tuple. +# +# @param value The time, given as an ISO 8601 string, a time +# tuple, or a integer time value. + +class DateTime: + """DateTime wrapper for an ISO 8601 string or time tuple or + localtime integer value to generate 'dateTime.iso8601' XML-RPC + value. + """ + + def __init__(self, value=0): + if not isinstance(value, StringType): + if datetime and isinstance(value, datetime.datetime): + self.value = value.strftime("%Y%m%dT%H:%M:%S") + return + if datetime and isinstance(value, datetime.date): + self.value = value.strftime("%Y%m%dT%H:%M:%S") + return + if datetime and isinstance(value, datetime.time): + today = datetime.datetime.now().strftime("%Y%m%d") + self.value = value.strftime(today+"T%H:%M:%S") + return + if not isinstance(value, (TupleType, time.struct_time)): + if value == 0: + value = time.time() + value = time.localtime(value) + value = time.strftime("%Y%m%dT%H:%M:%S", value) + self.value = value + + def __cmp__(self, other): + if isinstance(other, DateTime): + other = other.value + return cmp(self.value, other) + + ## + # Get date/time value. + # + # @return Date/time value, as an ISO 8601 string. + + def __str__(self): + return self.value + + def __repr__(self): + return "" % (repr(self.value), id(self)) + + def decode(self, data): + data = str(data) + self.value = string.strip(data) + + def encode(self, out): + out.write("") + out.write(self.value) + out.write("\n") + +def _datetime(data): + # decode xml element contents into a DateTime structure. + value = DateTime() + value.decode(data) + return value + +def _datetime_type(data): + t = time.strptime(data, "%Y%m%dT%H:%M:%S") + return datetime.datetime(*tuple(t)[:6]) + +## +# Wrapper for binary data. This can be used to transport any kind +# of binary data over XML-RPC, using BASE64 encoding. +# +# @param data An 8-bit string containing arbitrary data. + +import base64 +try: + import cStringIO as StringIO +except ImportError: + import StringIO + +class Binary: + """Wrapper for binary data.""" + + def __init__(self, data=None): + self.data = data + + ## + # Get buffer contents. + # + # @return Buffer contents, as an 8-bit string. + + def __str__(self): + return self.data or "" + + def __cmp__(self, other): + if isinstance(other, Binary): + other = other.data + return cmp(self.data, other) + + def decode(self, data): + self.data = base64.decodestring(data) + + def encode(self, out): + out.write("\n") + base64.encode(StringIO.StringIO(self.data), out) + out.write("\n") + +def _binary(data): + # decode xml element contents into a Binary structure + value = Binary() + value.decode(data) + return value + +WRAPPERS = (DateTime, Binary) +if not _bool_is_builtin: + WRAPPERS = WRAPPERS + (Boolean,) + +# -------------------------------------------------------------------- +# XML parsers + +try: + # optional xmlrpclib accelerator + import _xmlrpclib + FastParser = _xmlrpclib.Parser + FastUnmarshaller = _xmlrpclib.Unmarshaller +except (AttributeError, ImportError): + FastParser = FastUnmarshaller = None + +try: + import _xmlrpclib + FastMarshaller = _xmlrpclib.Marshaller +except (AttributeError, ImportError): + FastMarshaller = None + +# +# the SGMLOP parser is about 15x faster than Python's builtin +# XML parser. SGMLOP sources can be downloaded from: +# +# http://www.pythonware.com/products/xml/sgmlop.htm +# + +try: + import sgmlop + if not hasattr(sgmlop, "XMLParser"): + raise ImportError +except ImportError: + SgmlopParser = None # sgmlop accelerator not available +else: + class SgmlopParser: + def __init__(self, target): + + # setup callbacks + self.finish_starttag = target.start + self.finish_endtag = target.end + self.handle_data = target.data + self.handle_xml = target.xml + + # activate parser + self.parser = sgmlop.XMLParser() + self.parser.register(self) + self.feed = self.parser.feed + self.entity = { + "amp": "&", "gt": ">", "lt": "<", + "apos": "'", "quot": '"' + } + + def close(self): + try: + self.parser.close() + finally: + self.parser = self.feed = None # nuke circular reference + + def handle_proc(self, tag, attr): + m = re.search("encoding\s*=\s*['\"]([^\"']+)[\"']", attr) + if m: + self.handle_xml(m.group(1), 1) + + def handle_entityref(self, entity): + # entity + try: + self.handle_data(self.entity[entity]) + except KeyError: + self.handle_data("&%s;" % entity) + +try: + from xml.parsers import expat + if not hasattr(expat, "ParserCreate"): + raise ImportError +except ImportError: + ExpatParser = None # expat not available +else: + class ExpatParser: + # fast expat parser for Python 2.0 and later. this is about + # 50% slower than sgmlop, on roundtrip testing + def __init__(self, target): + self._parser = parser = expat.ParserCreate(None, None) + self._target = target + parser.StartElementHandler = target.start + parser.EndElementHandler = target.end + parser.CharacterDataHandler = target.data + encoding = None + if not parser.returns_unicode: + encoding = "utf-8" + target.xml(encoding, None) + + def feed(self, data): + self._parser.Parse(data, 0) + + def close(self): + self._parser.Parse("", 1) # end of data + del self._target, self._parser # get rid of circular references + +class SlowParser: + """Default XML parser (based on xmllib.XMLParser).""" + # this is about 10 times slower than sgmlop, on roundtrip + # testing. + def __init__(self, target): + import xmllib # lazy subclassing (!) + if xmllib.XMLParser not in SlowParser.__bases__: + SlowParser.__bases__ = (xmllib.XMLParser,) + self.handle_xml = target.xml + self.unknown_starttag = target.start + self.handle_data = target.data + self.handle_cdata = target.data + self.unknown_endtag = target.end + try: + xmllib.XMLParser.__init__(self, accept_utf8=1) + except TypeError: + xmllib.XMLParser.__init__(self) # pre-2.0 + +# -------------------------------------------------------------------- +# XML-RPC marshalling and unmarshalling code + +## +# XML-RPC marshaller. +# +# @param encoding Default encoding for 8-bit strings. The default +# value is None (interpreted as UTF-8). +# @see dumps + +class Marshaller: + """Generate an XML-RPC params chunk from a Python data structure. + + Create a Marshaller instance for each set of parameters, and use + the "dumps" method to convert your data (represented as a tuple) + to an XML-RPC params chunk. To write a fault response, pass a + Fault instance instead. You may prefer to use the "dumps" module + function for this purpose. + """ + + # by the way, if you don't understand what's going on in here, + # that's perfectly ok. + + def __init__(self, encoding=None, allow_none=0): + self.memo = {} + self.data = None + self.encoding = encoding + self.allow_none = allow_none + + dispatch = {} + + def dumps(self, values): + out = [] + write = out.append + dump = self.__dump + if isinstance(values, Fault): + # fault instance + write("\n") + dump({'faultCode': values.faultCode, + 'faultString': values.faultString}, + write) + write("\n") + else: + # parameter block + # FIXME: the xml-rpc specification allows us to leave out + # the entire block if there are no parameters. + # however, changing this may break older code (including + # old versions of xmlrpclib.py), so this is better left as + # is for now. See @XMLRPC3 for more information. /F + write("\n") + for v in values: + write("\n") + dump(v, write) + write("\n") + write("\n") + result = string.join(out, "") + return result + + def __dump(self, value, write): + try: + f = self.dispatch[type(value)] + except KeyError: + raise TypeError, "cannot marshal %s objects" % type(value) + else: + f(self, value, write) + + def dump_nil (self, value, write): + if not self.allow_none: + raise TypeError, "cannot marshal None unless allow_none is enabled" + write("") + dispatch[NoneType] = dump_nil + + def dump_int(self, value, write): + # in case ints are > 32 bits + #if value > MAXINT or value < MININT: + # raise OverflowError, "int exceeds XML-RPC limits" + write("") + write(str(value)) + write("\n") + dispatch[IntType] = dump_int + + if _bool_is_builtin: + def dump_bool(self, value, write): + write("") + write(value and "1" or "0") + write("\n") + dispatch[bool] = dump_bool + + def dump_long(self, value, write): + #if value > MAXINT or value < MININT: + # raise OverflowError, "long int exceeds XML-RPC limits" + write("") + write(str(int(value))) + write("\n") + dispatch[LongType] = dump_long + + def dump_double(self, value, write): + write("") + write(repr(value)) + write("\n") + dispatch[FloatType] = dump_double + + def dump_string(self, value, write, escape=escape): + write("") + write(escape(value)) + write("\n") + dispatch[StringType] = dump_string + + if unicode: + def dump_unicode(self, value, write, escape=escape): + value = value.encode(self.encoding) + write("") + write(escape(value)) + write("\n") + dispatch[UnicodeType] = dump_unicode + + def dump_array(self, value, write): + i = id(value) + if self.memo.has_key(i): + raise TypeError, "cannot marshal recursive sequences" + self.memo[i] = None + dump = self.__dump + write("\n") + for v in value: + dump(v, write) + write("\n") + del self.memo[i] + dispatch[TupleType] = dump_array + dispatch[ListType] = dump_array + + def dump_struct(self, value, write, escape=escape): + i = id(value) + if self.memo.has_key(i): + raise TypeError, "cannot marshal recursive dictionaries" + self.memo[i] = None + dump = self.__dump + write("\n") + for k, v in value.items(): + write("\n") + if type(k) is not StringType: + if unicode and type(k) is UnicodeType: + k = k.encode(self.encoding) + else: + raise TypeError, "dictionary key must be string" + write("%s\n" % escape(k)) + dump(v, write) + write("\n") + write("\n") + del self.memo[i] + dispatch[DictType] = dump_struct + + if datetime: + def dump_datetime(self, value, write): + write("") + write(value.strftime("%Y%m%dT%H:%M:%S")) + write("\n") + dispatch[datetime.datetime] = dump_datetime + + def dump_date(self, value, write): + write("") + write(value.strftime("%Y%m%dT00:00:00")) + write("\n") + dispatch[datetime.date] = dump_date + + def dump_time(self, value, write): + write("") + write(datetime.datetime.now().date().strftime("%Y%m%dT")) + write(value.strftime("%H:%M:%S")) + write("\n") + dispatch[datetime.time] = dump_time + + def dump_instance(self, value, write): + # check for special wrappers + if value.__class__ in WRAPPERS: + self.write = write + value.encode(self) + del self.write + else: + # store instance attributes as a struct (really?) + self.dump_struct(value.__dict__, write) + dispatch[InstanceType] = dump_instance + +## +# XML-RPC unmarshaller. +# +# @see loads + +class Unmarshaller: + """Unmarshal an XML-RPC response, based on incoming XML event + messages (start, data, end). Call close() to get the resulting + data structure. + + Note that this reader is fairly tolerant, and gladly accepts bogus + XML-RPC data without complaining (but not bogus XML). + """ + + # and again, if you don't understand what's going on in here, + # that's perfectly ok. + + def __init__(self, use_datetime=0): + self._type = None + self._stack = [] + self._marks = [] + self._data = [] + self._methodname = None + self._encoding = "utf-8" + self.append = self._stack.append + self._use_datetime = use_datetime + if use_datetime and not datetime: + raise ValueError, "the datetime module is not available" + + def close(self): + # return response tuple and target method + if self._type is None or self._marks: + raise ResponseError() + if self._type == "fault": + raise Fault(**self._stack[0]) + return tuple(self._stack) + + def getmethodname(self): + return self._methodname + + # + # event handlers + + def xml(self, encoding, standalone): + self._encoding = encoding + # FIXME: assert standalone == 1 ??? + + def start(self, tag, attrs): + # prepare to handle this element + if tag == "array" or tag == "struct": + self._marks.append(len(self._stack)) + self._data = [] + self._value = (tag == "value") + + def data(self, text): + self._data.append(text) + + def end(self, tag, join=string.join): + # call the appropriate end tag handler + try: + f = self.dispatch[tag] + except KeyError: + pass # unknown tag ? + else: + return f(self, join(self._data, "")) + + # + # accelerator support + + def end_dispatch(self, tag, data): + # dispatch data + try: + f = self.dispatch[tag] + except KeyError: + pass # unknown tag ? + else: + return f(self, data) + + # + # element decoders + + dispatch = {} + + def end_nil (self, data): + self.append(None) + self._value = 0 + dispatch["nil"] = end_nil + + def end_boolean(self, data): + if data == "0": + self.append(False) + elif data == "1": + self.append(True) + else: + raise TypeError, "bad boolean value" + self._value = 0 + dispatch["boolean"] = end_boolean + + def end_int(self, data): + self.append(int(data)) + self._value = 0 + dispatch["i4"] = end_int + dispatch["int"] = end_int + + def end_double(self, data): + self.append(float(data)) + self._value = 0 + dispatch["double"] = end_double + + def end_string(self, data): + if self._encoding: + data = _decode(data, self._encoding) + self.append(_stringify(data)) + self._value = 0 + dispatch["string"] = end_string + dispatch["name"] = end_string # struct keys are always strings + + def end_array(self, data): + mark = self._marks.pop() + # map arrays to Python lists + self._stack[mark:] = [self._stack[mark:]] + self._value = 0 + dispatch["array"] = end_array + + def end_struct(self, data): + mark = self._marks.pop() + # map structs to Python dictionaries + dict = {} + items = self._stack[mark:] + for i in range(0, len(items), 2): + dict[_stringify(items[i])] = items[i+1] + self._stack[mark:] = [dict] + self._value = 0 + dispatch["struct"] = end_struct + + def end_base64(self, data): + value = Binary() + value.decode(data) + self.append(value) + self._value = 0 + dispatch["base64"] = end_base64 + + def end_dateTime(self, data): + value = DateTime() + value.decode(data) + if self._use_datetime: + value = _datetime_type(data) + self.append(value) + dispatch["dateTime.iso8601"] = end_dateTime + + def end_value(self, data): + # if we stumble upon a value element with no internal + # elements, treat it as a string element + if self._value: + self.end_string(data) + dispatch["value"] = end_value + + def end_params(self, data): + self._type = "params" + dispatch["params"] = end_params + + def end_fault(self, data): + self._type = "fault" + dispatch["fault"] = end_fault + + def end_methodName(self, data): + if self._encoding: + data = _decode(data, self._encoding) + self._methodname = data + self._type = "methodName" # no params + dispatch["methodName"] = end_methodName + +## Multicall support +# + +class _MultiCallMethod: + # some lesser magic to store calls made to a MultiCall object + # for batch execution + def __init__(self, call_list, name): + self.__call_list = call_list + self.__name = name + def __getattr__(self, name): + return _MultiCallMethod(self.__call_list, "%s.%s" % (self.__name, name)) + def __call__(self, *args): + self.__call_list.append((self.__name, args)) + +class MultiCallIterator: + """Iterates over the results of a multicall. Exceptions are + thrown in response to xmlrpc faults.""" + + def __init__(self, results): + self.results = results + + def __getitem__(self, i): + item = self.results[i] + if type(item) == type({}): + raise Fault(item['faultCode'], item['faultString']) + elif type(item) == type([]): + return item[0] + else: + raise ValueError,\ + "unexpected type in multicall result" + +class MultiCall: + """server -> a object used to boxcar method calls + + server should be a ServerProxy object. + + Methods can be added to the MultiCall using normal + method call syntax e.g.: + + multicall = MultiCall(server_proxy) + multicall.add(2,3) + multicall.get_address("Guido") + + To execute the multicall, call the MultiCall object e.g.: + + add_result, address = multicall() + """ + + def __init__(self, server): + self.__server = server + self.__call_list = [] + + def __repr__(self): + return "" % id(self) + + __str__ = __repr__ + + def __getattr__(self, name): + return _MultiCallMethod(self.__call_list, name) + + def __call__(self): + marshalled_list = [] + for name, args in self.__call_list: + marshalled_list.append({'methodName' : name, 'params' : args}) + + return MultiCallIterator(self.__server.system.multicall(marshalled_list)) + + def get_call_list(self): + return self.__call_list + +# -------------------------------------------------------------------- +# convenience functions + +## +# Create a parser object, and connect it to an unmarshalling instance. +# This function picks the fastest available XML parser. +# +# return A (parser, unmarshaller) tuple. + +def getparser(use_datetime=0): + """getparser() -> parser, unmarshaller + + Create an instance of the fastest available parser, and attach it + to an unmarshalling object. Return both objects. + """ + if use_datetime and not datetime: + raise ValueError, "the datetime module is not available" + if FastParser and FastUnmarshaller: + if use_datetime: + mkdatetime = _datetime_type + else: + mkdatetime = _datetime + target = FastUnmarshaller(True, False, _binary, mkdatetime, Fault) + parser = FastParser(target) + else: + target = Unmarshaller(use_datetime=use_datetime) + if FastParser: + parser = FastParser(target) + elif SgmlopParser: + parser = SgmlopParser(target) + elif ExpatParser: + parser = ExpatParser(target) + else: + parser = SlowParser(target) + return parser, target + +## +# Convert a Python tuple or a Fault instance to an XML-RPC packet. +# +# @def dumps(params, **options) +# @param params A tuple or Fault instance. +# @keyparam methodname If given, create a methodCall request for +# this method name. +# @keyparam methodresponse If given, create a methodResponse packet. +# If used with a tuple, the tuple must be a singleton (that is, +# it must contain exactly one element). +# @keyparam encoding The packet encoding. +# @return A string containing marshalled data. + +def dumps(params, methodname=None, methodresponse=None, encoding=None, + allow_none=0): + """data [,options] -> marshalled data + + Convert an argument tuple or a Fault instance to an XML-RPC + request (or response, if the methodresponse option is used). + + In addition to the data object, the following options can be given + as keyword arguments: + + methodname: the method name for a methodCall packet + + methodresponse: true to create a methodResponse packet. + If this option is used with a tuple, the tuple must be + a singleton (i.e. it can contain only one element). + + encoding: the packet encoding (default is UTF-8) + + All 8-bit strings in the data structure are assumed to use the + packet encoding. Unicode strings are automatically converted, + where necessary. + """ + + assert isinstance(params, TupleType) or isinstance(params, Fault),\ + "argument must be tuple or Fault instance" + + if isinstance(params, Fault): + methodresponse = 1 + elif methodresponse and isinstance(params, TupleType): + assert len(params) == 1, "response tuple must be a singleton" + + if not encoding: + encoding = "utf-8" + + if FastMarshaller: + m = FastMarshaller(encoding) + else: + m = Marshaller(encoding, allow_none) + + data = m.dumps(params) + + if encoding != "utf-8": + xmlheader = "\n" % str(encoding) + else: + xmlheader = "\n" # utf-8 is default + + # standard XML-RPC wrappings + if methodname: + # a method call + if not isinstance(methodname, StringType): + methodname = methodname.encode(encoding) + data = ( + xmlheader, + "\n" + "", methodname, "\n", + data, + "\n" + ) + elif methodresponse: + # a method response, or a fault structure + data = ( + xmlheader, + "\n", + data, + "\n" + ) + else: + return data # return as is + return string.join(data, "") + +## +# Convert an XML-RPC packet to a Python object. If the XML-RPC packet +# represents a fault condition, this function raises a Fault exception. +# +# @param data An XML-RPC packet, given as an 8-bit string. +# @return A tuple containing the unpacked data, and the method name +# (None if not present). +# @see Fault + +def loads(data, use_datetime=0): + """data -> unmarshalled data, method name + + Convert an XML-RPC packet to unmarshalled data plus a method + name (None if not present). + + If the XML-RPC packet represents a fault condition, this function + raises a Fault exception. + """ + p, u = getparser(use_datetime=use_datetime) + p.feed(data) + p.close() + return u.close(), u.getmethodname() + + +# -------------------------------------------------------------------- +# request dispatcher + +class _Method: + # some magic to bind an XML-RPC method to an RPC server. + # supports "nested" methods (e.g. examples.getStateName) + def __init__(self, send, name): + self.__send = send + self.__name = name + def __getattr__(self, name): + return _Method(self.__send, "%s.%s" % (self.__name, name)) + def __call__(self, *args): + return self.__send(self.__name, args) + +## +# Standard transport class for XML-RPC over HTTP. +#

        +# You can create custom transports by subclassing this method, and +# overriding selected methods. + +class Transport: + """Handles an HTTP transaction to an XML-RPC server.""" + + # client identifier (may be overridden) + user_agent = "xmlrpclib.py/%s (by www.pythonware.com)" % __version__ + + def __init__(self, use_datetime=0): + self._use_datetime = use_datetime + + ## + # Send a complete request, and parse the response. + # + # @param host Target host. + # @param handler Target PRC handler. + # @param request_body XML-RPC request body. + # @param verbose Debugging flag. + # @return Parsed response. + + def request(self, host, handler, request_body, verbose=0): + # issue XML-RPC request + + h = self.make_connection(host) + if verbose: + h.set_debuglevel(1) + + self.send_request(h, handler, request_body) + self.send_host(h, host) + self.send_user_agent(h) + self.send_content(h, request_body) + + errcode, errmsg, headers = h.getreply() + + if errcode != 200: + raise ProtocolError( + host + handler, + errcode, errmsg, + headers + ) + + self.verbose = verbose + + try: + sock = h._conn.sock + except AttributeError: + sock = None + + return self._parse_response(h.getfile(), sock) + + ## + # Create parser. + # + # @return A 2-tuple containing a parser and a unmarshaller. + + def getparser(self): + # get parser and unmarshaller + return getparser(use_datetime=self._use_datetime) + + ## + # Get authorization info from host parameter + # Host may be a string, or a (host, x509-dict) tuple; if a string, + # it is checked for a "user:pw@host" format, and a "Basic + # Authentication" header is added if appropriate. + # + # @param host Host descriptor (URL or (URL, x509 info) tuple). + # @return A 3-tuple containing (actual host, extra headers, + # x509 info). The header and x509 fields may be None. + + def get_host_info(self, host): + + x509 = {} + if isinstance(host, TupleType): + host, x509 = host + + import urllib + auth, host = urllib.splituser(host) + + if auth: + import base64 + auth = base64.encodestring(urllib.unquote(auth)) + auth = string.join(string.split(auth), "") # get rid of whitespace + extra_headers = [ + ("Authorization", "Basic " + auth) + ] + else: + extra_headers = None + + return host, extra_headers, x509 + + ## + # Connect to server. + # + # @param host Target host. + # @return A connection handle. + + def make_connection(self, host): + # create a HTTP connection object from a host descriptor + import httplib + host, extra_headers, x509 = self.get_host_info(host) + return httplib.HTTP(host) + + ## + # Send request header. + # + # @param connection Connection handle. + # @param handler Target RPC handler. + # @param request_body XML-RPC body. + + def send_request(self, connection, handler, request_body): + connection.putrequest("POST", handler) + + ## + # Send host name. + # + # @param connection Connection handle. + # @param host Host name. + + def send_host(self, connection, host): + host, extra_headers, x509 = self.get_host_info(host) + connection.putheader("Host", host) + if extra_headers: + if isinstance(extra_headers, DictType): + extra_headers = extra_headers.items() + for key, value in extra_headers: + connection.putheader(key, value) + + ## + # Send user-agent identifier. + # + # @param connection Connection handle. + + def send_user_agent(self, connection): + connection.putheader("User-Agent", self.user_agent) + + ## + # Send request body. + # + # @param connection Connection handle. + # @param request_body XML-RPC request body. + + def send_content(self, connection, request_body): + connection.putheader("Content-Type", "text/xml") + connection.putheader("Content-Length", str(len(request_body))) + connection.endheaders() + if request_body: + connection.send(request_body) + + ## + # Parse response. + # + # @param file Stream. + # @return Response tuple and target method. + + def parse_response(self, file): + # compatibility interface + return self._parse_response(file, None) + + ## + # Parse response (alternate interface). This is similar to the + # parse_response method, but also provides direct access to the + # underlying socket object (where available). + # + # @param file Stream. + # @param sock Socket handle (or None, if the socket object + # could not be accessed). + # @return Response tuple and target method. + + def _parse_response(self, file, sock): + # read response from input file/socket, and parse it + + p, u = self.getparser() + + while 1: + if sock: + response = sock.recv(1024) + else: + response = file.read(1024) + if not response: + break + if self.verbose: + print "body:", repr(response) + p.feed(response) + + file.close() + p.close() + + return u.close() + +## +# Standard transport class for XML-RPC over HTTPS. + +class SafeTransport(Transport): + """Handles an HTTPS transaction to an XML-RPC server.""" + + # FIXME: mostly untested + + def make_connection(self, host): + # create a HTTPS connection object from a host descriptor + # host may be a string, or a (host, x509-dict) tuple + import httplib + host, extra_headers, x509 = self.get_host_info(host) + try: + HTTPS = httplib.HTTPS + except AttributeError: + raise NotImplementedError( + "your version of httplib doesn't support HTTPS" + ) + else: + return HTTPS(host, None, **(x509 or {})) + +## +# Standard server proxy. This class establishes a virtual connection +# to an XML-RPC server. +#

        +# This class is available as ServerProxy and Server. New code should +# use ServerProxy, to avoid confusion. +# +# @def ServerProxy(uri, **options) +# @param uri The connection point on the server. +# @keyparam transport A transport factory, compatible with the +# standard transport class. +# @keyparam encoding The default encoding used for 8-bit strings +# (default is UTF-8). +# @keyparam verbose Use a true value to enable debugging output. +# (printed to standard output). +# @see Transport + +class ServerProxy: + """uri [,options] -> a logical connection to an XML-RPC server + + uri is the connection point on the server, given as + scheme://host/target. + + The standard implementation always supports the "http" scheme. If + SSL socket support is available (Python 2.0), it also supports + "https". + + If the target part and the slash preceding it are both omitted, + "/RPC2" is assumed. + + The following options can be given as keyword arguments: + + transport: a transport factory + encoding: the request encoding (default is UTF-8) + + All 8-bit strings passed to the server proxy are assumed to use + the given encoding. + """ + + def __init__(self, uri, transport=None, encoding=None, verbose=0, + allow_none=0, use_datetime=0): + # establish a "logical" server connection + + # get the url + import urllib + type, uri = urllib.splittype(uri) + if type not in ("http", "https"): + raise IOError, "unsupported XML-RPC protocol" + self.__host, self.__handler = urllib.splithost(uri) + if not self.__handler: + self.__handler = "/RPC2" + + if transport is None: + if type == "https": + transport = SafeTransport(use_datetime=use_datetime) + else: + transport = Transport(use_datetime=use_datetime) + self.__transport = transport + + self.__encoding = encoding + self.__verbose = verbose + self.__allow_none = allow_none + + def __request(self, methodname, params): + # call a method on the remote server + + request = dumps(params, methodname, encoding=self.__encoding, + allow_none=self.__allow_none) + + response = self.__transport.request( + self.__host, + self.__handler, + request, + verbose=self.__verbose + ) + + if len(response) == 1: + response = response[0] + + return response + + def __repr__(self): + return ( + "" % + (self.__host, self.__handler) + ) + + __str__ = __repr__ + + def __getattr__(self, name): + # magic method dispatcher + return _Method(self.__request, name) + + # note: to call a remote object with an non-standard name, use + # result getattr(server, "strange-python-name")(args) + +# compatibility + +Server = ServerProxy + +# -------------------------------------------------------------------- +# test code + +if __name__ == "__main__": + + # simple test program (from the XML-RPC specification) + + # server = ServerProxy("http://localhost:8000") # local server + server = ServerProxy("http://time.xmlrpc.com/RPC2") + + print server + + try: + print server.currentTime.getCurrentTime() + except Error, v: + print "ERROR", v + + multi = MultiCall(server) + multi.currentTime.getCurrentTime() + multi.currentTime.getCurrentTime() + try: + for response in multi(): + print response + except Error, v: + print "ERROR", v diff --git a/ez_setup.py b/ez_setup.py new file mode 100644 index 000000000..bfda8cd7d --- /dev/null +++ b/ez_setup.py @@ -0,0 +1,231 @@ +#!python +"""Bootstrap setuptools installation + +If you want to use setuptools in your package's setup.py, just include this +file in the same directory with it, and add this to the top of your setup.py:: + + from ez_setup import use_setuptools + use_setuptools() + +If you want to require a specific version of setuptools, set a download +mirror, or use an alternate download directory, you can do so by supplying +the appropriate options to ``use_setuptools()``. + +This file can also be run as a script to install or upgrade setuptools. +""" +import sys +DEFAULT_VERSION = "0.6c6" +DEFAULT_URL = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3] + +md5_data = { + 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', + 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', + 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', + 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', + 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', + 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', + 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', + 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', + 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', + 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', + 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', + 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', + 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', + 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', + 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', + 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', + 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', + 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', + 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', + 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', + 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', + 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20', + 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab', + 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53', +} + +import sys, os + +def _validate_md5(egg_name, data): + if egg_name in md5_data: + from md5 import md5 + digest = md5(data).hexdigest() + if digest != md5_data[egg_name]: + print >>sys.stderr, ( + "md5 validation of %s failed! (Possible download problem?)" + % egg_name + ) + sys.exit(2) + return data + + +def use_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, + download_delay=15 +): + """Automatically find/download setuptools and make it available on sys.path + + `version` should be a valid setuptools version number that is available + as an egg for download under the `download_base` URL (which should end with + a '/'). `to_dir` is the directory where setuptools will be downloaded, if + it is not already available. If `download_delay` is specified, it should + be the number of seconds that will be paused before initiating a download, + should one be required. If an older version of setuptools is installed, + this routine will print a message to ``sys.stderr`` and raise SystemExit in + an attempt to abort the calling script. + """ + try: + import setuptools + if setuptools.__version__ == '0.0.1': + print >>sys.stderr, ( + "You have an obsolete version of setuptools installed. Please\n" + "remove it from your system entirely before rerunning this script." + ) + sys.exit(2) + except ImportError: + egg = download_setuptools(version, download_base, to_dir, download_delay) + sys.path.insert(0, egg) + import setuptools; setuptools.bootstrap_install_from = egg + + import pkg_resources + try: + pkg_resources.require("setuptools>="+version) + + except pkg_resources.VersionConflict, e: + # XXX could we install in a subprocess here? + print >>sys.stderr, ( + "The required version of setuptools (>=%s) is not available, and\n" + "can't be installed while this script is running. Please install\n" + " a more recent version first.\n\n(Currently using %r)" + ) % (version, e.args[0]) + sys.exit(2) + +def download_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, + delay = 15 +): + """Download setuptools from a specified location and return its filename + + `version` should be a valid setuptools version number that is available + as an egg for download under the `download_base` URL (which should end + with a '/'). `to_dir` is the directory where the egg will be downloaded. + `delay` is the number of seconds to pause before an actual download attempt. + """ + import urllib2, shutil + egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) + url = download_base + egg_name + saveto = os.path.join(to_dir, egg_name) + src = dst = None + if not os.path.exists(saveto): # Avoid repeated downloads + try: + from distutils import log + if delay: + log.warn(""" +--------------------------------------------------------------------------- +This script requires setuptools version %s to run (even to display +help). I will attempt to download it for you (from +%s), but +you may need to enable firewall access for this script first. +I will start the download in %d seconds. + +(Note: if this machine does not have network access, please obtain the file + + %s + +and place it in this directory before rerunning this script.) +---------------------------------------------------------------------------""", + version, download_base, delay, url + ); from time import sleep; sleep(delay) + log.warn("Downloading %s", url) + src = urllib2.urlopen(url) + # Read/write all in one block, so we don't create a corrupt file + # if the download is interrupted. + data = _validate_md5(egg_name, src.read()) + dst = open(saveto,"wb"); dst.write(data) + finally: + if src: src.close() + if dst: dst.close() + return os.path.realpath(saveto) + +def main(argv, version=DEFAULT_VERSION): + """Install or upgrade setuptools and EasyInstall""" + + try: + import setuptools + except ImportError: + egg = None + try: + egg = download_setuptools(version, delay=0) + sys.path.insert(0,egg) + from setuptools.command.easy_install import main + return main(list(argv)+[egg]) # we're done here + finally: + if egg and os.path.exists(egg): + os.unlink(egg) + else: + if setuptools.__version__ == '0.0.1': + # tell the user to uninstall obsolete version + use_setuptools(version) + + req = "setuptools>="+version + import pkg_resources + try: + pkg_resources.require(req) + except pkg_resources.VersionConflict: + try: + from setuptools.command.easy_install import main + except ImportError: + from easy_install import main + main(list(argv)+[download_setuptools(delay=0)]) + sys.exit(0) # try to force an exit + else: + if argv: + from setuptools.command.easy_install import main + main(argv) + else: + print "Setuptools version",version,"or greater has been installed." + print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' + + + +def update_md5(filenames): + """Update our built-in md5 registry""" + + import re + from md5 import md5 + + for name in filenames: + base = os.path.basename(name) + f = open(name,'rb') + md5_data[base] = md5(f.read()).hexdigest() + f.close() + + data = [" %r: %r,\n" % it for it in md5_data.items()] + data.sort() + repl = "".join(data) + + import inspect + srcfile = inspect.getsourcefile(sys.modules[__name__]) + f = open(srcfile, 'rb'); src = f.read(); f.close() + + match = re.search("\nmd5_data = {\n([^}]+)}", src) + if not match: + print >>sys.stderr, "Internal error!" + sys.exit(2) + + src = src[:match.start(1)] + repl + src[match.end(1):] + f = open(srcfile,'w') + f.write(src) + f.close() + + +if __name__=='__main__': + if len(sys.argv)>2 and sys.argv[1]=='--md5update': + update_md5(sys.argv[2:]) + else: + main(sys.argv[1:]) + + + + + diff --git a/gettextize.sh b/gettextize.sh old mode 100755 new mode 100644 index c592e2e7e..281903741 --- a/gettextize.sh +++ b/gettextize.sh @@ -1,2 +1,2 @@ #!/bin/sh -xgettext -f po/POTFILES.in -o po/deluge.pot +xgettext -f deluge/i18n/POTFILES.in -o deluge/i18n/deluge.pot diff --git a/glade/aboutdialog.glade b/glade/aboutdialog.glade deleted file mode 100644 index 78c924d90..000000000 --- a/glade/aboutdialog.glade +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - True - True - 5 - True - GTK_WIN_POS_CENTER_ALWAYS - True - GDK_WINDOW_TYPE_HINT_NORMAL - True - False - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_BUTTONBOX_END - - - False - GTK_PACK_END - - - - - - diff --git a/glade/delugegtk.glade b/glade/delugegtk.glade deleted file mode 100644 index 5204d6705..000000000 --- a/glade/delugegtk.glade +++ /dev/null @@ -1,1363 +0,0 @@ - - - - - - Deluge - - - - - - True - 4 - 3 - - - - - - - - - True - GTK_ICON_SIZE_SMALL_TOOLBAR - True - - - True - Add Torrent - Add - True - gtk-add - - - - False - - - - - True - False - Remove Torrent - Remove - True - gtk-remove - - - - False - - - - - True - Clear Seeding Torrents - Clear - True - gtk-clear - - - - False - - - - - True - - - False - False - - - - - True - False - Start or Resume Torrent - Resume - True - gtk-media-play - - - - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Pause Torrent - Pause - gtk-media-pause - - - - False - - - - - True - False - Queue Torrent Up - Up - True - gtk-go-up - - - - False - - - - - True - False - Queue Torrent Down - Down - True - gtk-go-down - - - - False - - - - - True - - - False - False - - - - - True - Change Deluge preferences - Preferences - True - gtk-preferences - - - - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Plugins - gtk-disconnect - - - - False - - - - - True - - - False - False - - - - - 1 - 2 - GTK_FILL - - - - - True - - - True - _File - True - - - - - True - _Add Torrent - True - - - - True - gtk-add - 1 - - - - - - - True - Add _URL - True - - - - - - True - _Clear Completed - True - - - - True - gtk-clear - 1 - - - - - - - True - - - - - True - gtk-quit - True - True - - - - - - - - - - True - _Edit - True - - - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-select-all - True - True - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Plu_gins - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-disconnect - - - - - - - True - gtk-preferences - True - True - - - - - - - - - - True - _Torrent - True - - - - - True - _View - True - - - True - - - True - _Toolbar - True - True - - - - - - True - _Details - True - True - - - - - - True - _Columns - True - - - True - - - True - Size - True - True - - - - - - True - Status - True - True - - - - - - True - Seeders - True - True - - - - - - True - Peers - True - True - - - - - - True - Down Speed - True - True - - - - - - True - Up Speed - True - True - - - - - - True - Time Remaining - True - True - - - - - - True - Availability - True - True - - - - - - True - Share Ratio - True - True - - - - - - - - - - - - - - True - _Help - True - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Donate to Deluge Development - _Donate - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-yes - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Homepage - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-home - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _FAQ - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-dialog-question - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Community - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-info - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Help translate this application - _Translate This Application... - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-edit - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Runs the first-time configuration wizard - _Run Configuration Wizard - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-preferences - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - True - gtk-about - True - True - - - - - - - - - - 3 - - - - - - True - - - 3 - 3 - 4 - - - - - - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - True - True - True - False - - - - - - - True - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - True - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_NEVER - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_RESIZE_QUEUE - GTK_SHADOW_NONE - - - True - 1 - 2 - 10 - - - True - 0 - - - True - 10 - 10 - 15 - 15 - - - True - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_RESIZE_QUEUE - GTK_SHADOW_NONE - - - 25 - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - - - - True - 0.10000000149 - - - False - False - 1 - - - - - True - 5 - 4 - 5 - - - True - 0 - - - 1 - 2 - - - - - True - 0 - - - 3 - 4 - - - - - True - 0 - - - 1 - 2 - 1 - 2 - - - - - True - 0 - - - 3 - 4 - 1 - 2 - - - - - True - 0 - - - 1 - 2 - 2 - 3 - - - - - True - 0 - - - 3 - 4 - 2 - 3 - - - - - True - 0 - - - 1 - 2 - 3 - 4 - - - - - True - 0 - - - 3 - 4 - 3 - 4 - - - - - True - 5 - - - True - 0 - <b>Downloaded:</b> - True - - - - - - - True - 5 - - - True - 0 - <b>Uploaded:</b> - True - - - - - 1 - 2 - - - - - True - 5 - - - True - 0 - <b>Seeders:</b> - True - - - - - 2 - 3 - - - - - True - 5 - - - True - 0 - <b>Share Ratio:</b> - True - - - - - 3 - 4 - - - - - True - 15 - 5 - - - True - 0 - <b>Speed:</b> - True - - - - - 2 - 3 - - - - - True - 15 - 5 - - - True - 0 - <b>Speed:</b> - True - - - - - 2 - 3 - 1 - 2 - - - - - True - 15 - 5 - - - True - 0 - <b>Peers:</b> - True - - - - - 2 - 3 - 2 - 3 - - - - - True - 15 - 5 - - - True - 0 - <b>ETA:</b> - True - - - - - 2 - 3 - 3 - 4 - - - - - True - 0 - 1 - <b>Pieces:</b> - True - - - 4 - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - 0 - - - - - 1 - 2 - 4 - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 15 - 5 - - - True - 0 - 1 - <b>Availability:</b> - True - - - - - 2 - 3 - 4 - 5 - - - - - True - 0 - True - PANGO_WRAP_WORD_CHAR - - - 3 - 4 - 4 - 5 - - - - - - False - 2 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Statistics</b> - True - - - label_item - - - - - - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - 10 - 15 - 15 - - - True - 7 - 2 - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - 0 - 1 - <b># of files:</b> - True - - - - - 3 - 4 - GTK_FILL - - - - - True - 0 - True - - - 1 - 2 - 3 - 4 - - - - - - True - 0 - True - - - 1 - 2 - 2 - 3 - - - - - - True - 0 - True - PANGO_WRAP_CHAR - True - - - 1 - 2 - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - 0 - 1 - <b>Total Size:</b> - True - - - - - 2 - 3 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - 0 - 1 - <b>Tracker:</b> - True - - - - - 4 - 5 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - 0 - 1 - <b>Tracker Status:</b> - True - - - - - 5 - 6 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - 0 - 1 - <b>Next Announce:</b> - True - - - - - 6 - 7 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - 0 - 0 - 1 - <b>Name:</b> - True - - - - - GTK_FILL - - - - - True - 0 - True - PANGO_WRAP_CHAR - True - - - 1 - 2 - 4 - 5 - - - - - - True - 0 - True - PANGO_WRAP_CHAR - True - - - 1 - 2 - 5 - 6 - - - - - - True - 0 - True - True - - - 1 - 2 - 6 - 7 - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - <b>Path:</b> - True - - - - - 1 - 2 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - True - PANGO_WRAP_CHAR - True - - - 1 - 2 - 1 - 2 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Torrent Info</b> - True - - - label_item - - - - - 1 - 2 - GTK_FILL - - - - - - - - - True - - - - - True - Details - - - tab - False - - - - - - - False - False - - - - - 3 - 2 - 3 - - - - - - diff --git a/glade/dgtkpopups.glade b/glade/dgtkpopups.glade deleted file mode 100644 index 47dadaa07..000000000 --- a/glade/dgtkpopups.glade +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - Remove Torrent - GTK_WIN_POS_CENTER_ON_PARENT - True - GDK_WINDOW_TYPE_HINT_DIALOG - True - True - False - - - True - - - True - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-dialog-warning - 6 - - - False - False - 5 - - - - - True - 0 - <span size="large"><b>Are you sure you want to remove the selected torrent(s) from Deluge?</b></span> - True - True - - - 10 - 1 - - - - - False - False - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 20 - - - True - Delete downloaded files - 0 - True - - - - - False - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 20 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Delete .torrent file - 0 - True - True - - - - - False - False - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 3 - - - - - False - False - 5 - 1 - - - - - True - GTK_BUTTONBOX_END - - - True - gtk-no - True - 0 - - - - - True - gtk-yes - True - 1 - - - 1 - - - - - False - GTK_PACK_END - - - - - - - True - - - True - Show/Hide - True - - - - - - True - Add a Torrent... - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-add - 1 - - - - - - - True - Clear Finished - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-clear - 1 - - - - - - - True - - - - - True - gtk-preferences - True - True - - - - - - True - Plugins - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-execute - 1 - - - - - - - True - - - - - True - gtk-quit - True - True - - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - GTK_WIN_POS_MOUSE - True - GDK_WINDOW_TYPE_HINT_DIALOG - True - False - False - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - False - - - - - True - True - True - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - 1 - 0 -1 10000 1 10 10 - True - - - False - False - 1 - - - - - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_BUTTONBOX_END - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-cancel - True - 0 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-ok - True - 1 - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/glade/edit_trackers.glade b/glade/edit_trackers.glade deleted file mode 100644 index 15d4f6d9d..000000000 --- a/glade/edit_trackers.glade +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - 300 - 200 - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Edit Trackers - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 36 - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Tracker Editing - - - False - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - 1 - - - - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-cancel - True - 0 - - - - False - False - 1 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-ok - True - 0 - - - - False - False - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - 1 - - - - - - 3 - - - - - False - False - 2 - - - - - - diff --git a/glade/file_tab_menu.glade b/glade/file_tab_menu.glade deleted file mode 100644 index f93eef209..000000000 --- a/glade/file_tab_menu.glade +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Open File - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-open - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - True - Select All - True - - - - True - gtk-select-all - 1 - - - - - - - True - Unselect All - True - - - - True - gtk-missing-image - 1 - - - - - - - True - - - - - True - Don't download - True - - - - True - gtk-ok - 1 - - - - - - - True - Normal - True - - - - True - gtk-ok - 1 - - - - - - - True - High - True - - - - True - gtk-ok - 1 - - - - - - - True - Highest - True - - - - True - gtk-ok - 1 - - - - - - diff --git a/glade/files_dialog.glade b/glade/files_dialog.glade deleted file mode 100644 index 290322df0..000000000 --- a/glade/files_dialog.glade +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Deluge File Selection - GTK_WIN_POS_CENTER_ALWAYS - 550 - 550 - True - GDK_WINDOW_TYPE_HINT_DIALOG - True - True - False - - - True - 1 - - - True - True - - - True - True - - - - - 2 - 1 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Torrent will not be distributed on the trackerless (DHT) network - Set the private flag - 0 - True - - - False - False - 2 - - - - - True - GTK_BUTTONBOX_END - - - True - gtk-cancel - True - 0 - - - - - True - gtk-ok - True - 1 - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/glade/merge_dialog.glade b/glade/merge_dialog.glade deleted file mode 100644 index 986bd154b..000000000 --- a/glade/merge_dialog.glade +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - 5 - Deluge Merge Tracker Lists - GTK_WIN_POS_CENTER_ALWAYS - 200 - 50 - False - True - True - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - 2 - - - True - Torrent already detected in Deluge, would you like to merge the tracker lists? - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - GTK_BUTTONBOX_END - - - True - gtk-cancel - True - 0 - - - - - True - gtk-ok - True - 1 - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/glade/preferences_dialog.glade b/glade/preferences_dialog.glade deleted file mode 100644 index 6ed802094..000000000 --- a/glade/preferences_dialog.glade +++ /dev/null @@ -1,2927 +0,0 @@ - - - - - - 516 - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Deluge Preferences - GTK_WIN_POS_CENTER_ON_PARENT - 550 - True - GDK_WINDOW_TYPE_HINT_NORMAL - True - True - False - - - True - 1 - - - True - True - True - - - True - True - GTK_POLICY_NEVER - GTK_POLICY_AUTOMATIC - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_SHADOW_NONE - - - True - 2 - - - True - 0 - GTK_SHADOW_NONE - - - True - 2 - 2 - 12 - - - True - - - True - Ask where to save each download - True - 0 - 0 - True - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER - Select A Folder - - - 1 - 2 - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Store all torrent files in: - - - 1 - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER - Select A Folder - - - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Store all downloads in: - Store all downloads in: - 0 - 0 - True - True - radio_ask_save - - - - - - 1 - - - - - - - - - True - <b>Download Location</b> - True - - - label_item - - - - - False - False - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 1 - 2 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Autoload all torrent files in: - 0 - 0 - True - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER - Select A Folder - - - - - 1 - 2 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Autoload</b> - True - - - label_item - - - - - False - False - 2 - 1 - - - - - True - 0 - GTK_SHADOW_NONE - - - True - 2 - 2 - 12 - - - True - - - True - 10 - - - True - The number of active torrents that Deluge will run. Set to -1 for unlimited. - 0 - Maximum simultaneous active torrents: - - - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The number of active torrents that Deluge will run. Set to -1 for unlimited. - 1 - -1 -1 1000 1 10 10 - 1 - True - GTK_UPDATE_IF_VALID - - - - - False - 2 - 1 - - - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Enable selecting files for torrents before loading - Enable selecting files for torrents before loading - 0 - 0 - True - - - - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Enable selecting files for torrents before loading - Only show if torrent has more than 1 file - 0 - 0 - True - - - - - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Prioritize first and last pieces of files in torrent - Prioritize first and last pieces of files in torrent - 0 - 0 - True - - - False - 3 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Start torrents in paused state - 0 - 0 - True - - - 4 - - - - - - - - - True - <b>Torrents</b> - True - - - label_item - - - - - False - False - 2 - 2 - - - - - True - 0 - GTK_SHADOW_NONE - - - True - 2 - 2 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Full allocation preallocates all of the space that is needed for the torrent and prevents disk fragmentation - Use Full Allocation - 0 - True - True - - - - - False - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 45 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Compact allocation only allocates space as needed - Use Compact Allocation - 0 - True - radio_full_allocation - - - - - False - False - 1 - - - - - - - - - True - <b>Allocation</b> - True - - - label_item - - - - - False - False - 2 - 3 - - - - - - - - - - - True - Downloads - - - tab - False - - - - - True - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_SHADOW_NONE - - - True - - - True - - - True - 2 - - - True - gtk-dialog-warning - 6 - - - False - False - 10 - - - - - True - 0.20000000298023224 - <b>Please Note - Changes to these settings will only be applied the next time Deluge is restarted.</b> - True - True - 0 - - - False - False - 1 - - - - - False - False - 5 - - - - - False - - - - - True - 0 - GTK_SHADOW_NONE - - - True - 2 - 2 - 12 - - - True - - - True - - - True - From: - - - False - - - - - True - True - 0 0 65535 1 10 10 - 1 - - - False - 5 - 1 - - - - - True - 5 - To: - - - False - False - 2 - - - - - True - True - 0 0 65535 1 10 10 - 1 - - - False - 5 - 3 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Deluge will automatically choose a different port to use every time. - Random Ports - 0 - True - - - - False - 5 - 4 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Test Active Port - 0 - - - - False - False - 5 - - - - - 5 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - <b>TCP</b> - True - - - False - 5 - - - - - True - 1 - Active Port: - GTK_JUSTIFY_RIGHT - - - False - 5 - 1 - - - - - True - 0 - 0000 - 5 - - - False - 5 - 2 - - - - - label_item - - - - - False - 2 - 1 - - - - - True - 0 - GTK_SHADOW_NONE - - - True - 2 - 2 - 12 - - - True - - - True - True - Distributed hash table may improve the amount of active connections. - Enable Mainline DHT - True - 0 - True - - - - - - - - - True - <b>DHT</b> - True - - - label_item - - - - - False - 2 - 2 - - - - - True - - - True - 0 - GTK_SHADOW_NONE - - - True - 2 - 2 - 12 - - - True - - - True - True - Universal Plug and Play - UPnP - True - 0 - True - True - - - 2 - - - - - True - True - NAT Port Mapping Protocol - NAT-PMP - True - 0 - True - True - - - 2 - 1 - - - - - True - True - Peer Exchange - Peer Exchange - True - 0 - True - True - - - 2 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Local Peer Discovery - 0 - True - - - 3 - - - - - - - - - True - <b>Network Extras</b> - True - - - label_item - - - - - 2 - - - - - False - False - 3 - - - - - True - 0 - GTK_SHADOW_NONE - - - True - 2 - 2 - 12 - - - True - 2 - - - True - - - True - 1 - Inbound: - - - False - - - - - True - Disabled -Enabled -Forced - - - 5 - 1 - - - - - True - 1 - Outbound: - - - 2 - - - - - True - Disabled -Enabled -Forced - - - 5 - 3 - - - - - - - True - - - True - True - Prefer to encrypt the entire stream - True - 0 - True - - - False - - - - - True - 1 - Level: - - - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 7 - - - True - Handshake -Full Stream -Either - - - - - 6 - 2 - - - - - 1 - - - - - - - - - True - <b>Encryption</b> - True - - - label_item - - - - - False - False - 2 - 4 - - - - - - - - - - - - 1 - - - - - True - Network - - - tab - 1 - False - - - - - True - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - 0 - GTK_SHADOW_NONE - - - True - 2 - 2 - 12 - - - True - - - True - True - Queue torrents to bottom when they begin seeding - True - 0 - True - - - - - - True - False - True - Queue new torrents above completed ones - True - 0 - True - - - 1 - - - - - True - 10 - - - True - Stop seeding torrents when their share ratio reaches: - True - 0 - True - - - - False - - - - - True - False - True - 1 - 0 0 100 0.050000000745099998 10 9 - 1 - 2 - True - - - False - 1 - - - - - 2 - - - - - True - False - True - Automatically clear torrents that reach the max share ratio - True - 0 - True - - - 3 - - - - - True - 10 - - - True - Stop seeding torrents when their seed time reaches: - True - 0 - True - - - - False - - - - - True - False - True - Number of hours - 1 - 0 0 100 0.050000000745099998 10 9 - 1 - 2 - True - - - False - 1 - - - - - 4 - - - - - True - False - True - Automatically clear torrents that reach the max seed time - True - 0 - True - - - 5 - - - - - - - - - True - <b>Seeding</b> - True - - - label_item - - - - - False - False - - - - - - - - - - - - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Seeding - - - tab - 2 - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_RESIZE_QUEUE - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - 0 - GTK_SHADOW_NONE - - - True - 2 - 2 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - 2 - - - True - True - The maximum number of connection attempts per second. A high value may crash some cheap routers. Set -1 for unlimited. - 1 - -1 -1 9000 1 10 10 - 1 - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - True - The maximum number of connection attempts per second. A high value may crash some cheap routers. Set -1 for unlimited. - 0 - Maximum Connection Attempts per Second: - - - 5 - 6 - - - - - True - True - The maximum upload slots for all torrents. Set -1 for unlimited. - 1 - -1 -1 9000 1 10 10 - 1 - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - The maximum upload speed for all torrents. Set -1 for unlimited. - 1 - 0 -1 9000 1 10 10 - 1 - 1 - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The maximum download speed for all torrents. Set -1 for unlimited. - 1 - 0 -1 9000 1 10 10 - 1 - 1 - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - The maximum download speed for all torrents. Set -1 for unlimited. - 0 - Maximum Download Speed (KiB/s): - - - 1 - 2 - - - - - True - True - The maximum number of connections allowed. Set -1 for unlimited. - 1 - -1 -1 1000 1 10 10 - 1 - - - 1 - 2 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - The maximum number of connections allowed. Set -1 for unlimited. - 0 - Maximum Connections: - - - - - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - The maximum upload speed for all torrents. Set -1 for unlimited. - 0 - Maximum Upload Speed (KiB/s): - - - - - 2 - 3 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - The maximum upload speed for all torrents. Set -1 for unlimited. - 0 - Maximum Upload Slots: - - - - - 3 - 4 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - The maximum half-open connections. A high value may crash some cheap routers. Set -1 for unlimited. - 0 - Maximum Half-Open Connections: - - - - - 4 - 5 - GTK_FILL - - - - - True - True - The maximum half-open connections. A high value may crash some cheap routers. Set -1 for unlimited. - 1 - -1 -1 9000 1 10 10 - 1 - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - - - - - True - <b>Global Bandwidth Usage</b> - True - - - label_item - - - - - False - False - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 2 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 2 - - - True - True - The maximum upload slots per torrent. Set -1 for unlimited. - 1 - -1 -1 1000 1 10 10 - 1 - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - The maximum number of connections per torrent. Set -1 for unlimited. - 1 - -1 -1 1000 1 10 10 - - - 1 - 2 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The maximum upload slots per torrent. Set -1 for unlimited. - 0 - Maximum Upload Slots: - - - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The maximum number of connections per torrent. Set -1 for unlimited. - 0 - Maximum Connections: - - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Per Torrent Bandwidth Usage</b> - True - - - label_item - - - - - False - 1 - - - - - - - - - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Bandwidth - - - tab - 3 - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_RESIZE_QUEUE - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - - True - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Affects regular bittorrent peers - Peer Proxy - 0 - True - - - - - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - 4 - - - - - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 8080 0 65000 1 10 10 - - - 3 - 4 - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Port - - - 2 - 3 - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Server - - - 2 - 3 - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - - - 1 - 2 - 2 - 3 - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 1 - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - None -Socksv4 -Socksv5 -Socksv5 W/ Auth -HTTP -HTTP W/ Auth - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Password - - - 2 - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Username - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Proxy type - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 3 - 4 - - - - - 1 - - - - - - - True - <b>Peer Proxy</b> - True - - - label_item - - - - - False - 2 - 1 - - - - - True - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Affects regular bittorrent peers - Tracker Proxy - 0 - True - - - - - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - 4 - - - - - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 8080 0 65000 1 10 10 - - - 3 - 4 - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Port - - - 2 - 3 - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Server - - - 2 - 3 - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - - - 1 - 2 - 2 - 3 - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 1 - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - None -Socksv4 -Socksv5 -Socksv5 W/ Auth -HTTP -HTTP W/ Auth - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Password - - - 2 - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Username - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Proxy type - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 3 - 4 - - - - - 1 - - - - - - - True - <b>Tracker Proxy</b> - True - - - label_item - - - - - False - 2 - 2 - - - - - True - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Affects regular bittorrent peers - DHT Proxy - 0 - True - - - - - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - 4 - - - - - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 8080 0 65000 1 10 10 - - - 3 - 4 - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Port - - - 2 - 3 - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Server - - - 2 - 3 - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - - - 1 - 2 - 2 - 3 - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 1 - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - None -Socksv4 -Socksv5 -Socksv5 W/ Auth -HTTP -HTTP W/ Auth - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Password - - - 2 - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Username - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Proxy type - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 3 - 4 - - - - - 1 - - - - - - - True - <b>DHT Proxy</b> - True - - - label_item - - - - - False - 2 - 3 - - - - - True - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Affects regular bittorrent peers - Web Seed Proxy - 0 - True - - - - - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - 4 - - - - - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 8080 0 65000 1 10 10 - - - 3 - 4 - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Port - - - 2 - 3 - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Server - - - 2 - 3 - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - - - 1 - 2 - 2 - 3 - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 1 - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - None -Socksv4 -Socksv5 -Socksv5 W/ Auth -HTTP -HTTP W/ Auth - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Password - - - 2 - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Username - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Proxy type - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 3 - 4 - - - - - 1 - - - - - - - True - <b>Web Seed Proxy</b> - True - - - label_item - - - - - False - 2 - 4 - - - - - - - - - 4 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Proxies - - - tab - 4 - False - - - - - True - 2 - - - True - 0 - GTK_SHADOW_NONE - - - True - 12 - - - True - True - Have messages will be sent to peers that already have the piece. It adds a little overhead, but allows other clients to see our progress. - Send Redundant Have - 0 - True - - - - - - - True - <b>Peers</b> - True - - - label_item - - - - - False - - - - - True - 0 - GTK_SHADOW_NONE - - - True - 2 - 2 - 12 - - - True - - - True - Enable system tray icon - True - 0 - 0 - True - True - - - - - - True - 10 - - - True - False - Minimize to tray on close - True - 0 - 0 - True - - - - - 1 - - - - - True - 10 - - - True - False - Start in tray - True - 0 - 0 - True - - - - - 2 - - - - - True - 3 - 10 - - - True - - - True - False - True - Password protect system tray - True - 0 - 0 - True - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - - - True - 5 - - - True - 0 - Password: - - - - - False - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - 16 - - - False - 1 - - - - - - - 1 - - - - - - - False - 3 - - - - - - - - - True - <b>System Tray</b> - True - - - label_item - - - - - False - 2 - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Use the advanced progress bar (uses slightly more CPU/RAM) - 0 - True - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Detailed Progress Bar</b> - True - - - label_item - - - - - False - False - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Deluge will check our servers and will tell you if a newer version has been released - Be alerted about new releases - 0 - True - - - False - False - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Updates</b> - True - - - label_item - - - - - False - False - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Help us improve Deluge by sending us your Python and PyGTK -versions, OS and processor types. Absolutely no other -information is sent. - 0 - True - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>System Information</b> - True - - - label_item - - - - - False - False - 4 - - - - - - - - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Other - - - tab - 5 - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 350 - 150 - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_RESIZE_QUEUE - - - True - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - False - 1 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_RESIZE_QUEUE - - - 350 - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - GTK_WRAP_WORD - False - False - - - - - - - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 168 - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-preferences - True - 0 - - - - - - False - False - - - - - False - False - 3 - - - - - 6 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Plugins - - - tab - 6 - False - - - - - 2 - 2 - - - - - True - GTK_BUTTONBOX_END - - - True - gtk-cancel - True - 0 - - - - - True - gtk-ok - True - 1 - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/glade/torrent_menu.glade b/glade/torrent_menu.glade deleted file mode 100644 index e5e8538ac..000000000 --- a/glade/torrent_menu.glade +++ /dev/null @@ -1,263 +0,0 @@ - - - - - - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Force Recheck - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-redo - 1 - - - - - - - True - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Re_sume - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-media-play - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Pause - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-media-pause - 1 - - - - - - - True - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Remove Torrent - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-remove - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Tracker Options - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - _Update Tracker - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-refresh - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Edit Trackers - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-edit - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Scrape Tracker - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-info - 1 - - - - - - - - - - - True - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Queue - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Top - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-goto-top - 1 - - - - - - - True - _Up - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-go-up - 1 - - - - - - - True - _Down - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-go-down - 1 - - - - - - - True - _Bottom - True - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-goto-bottom - 1 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-sort-ascending - 1 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Open Containing Folder - True - - - - gtk-open - 1 - - - - - - diff --git a/glade/wizard.glade b/glade/wizard.glade deleted file mode 100644 index 43c6e6c0e..000000000 --- a/glade/wizard.glade +++ /dev/null @@ -1,520 +0,0 @@ - - - - - - 500 - 335 - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - First Launch Configuration - GTK_WIN_POS_CENTER - GDK_WINDOW_TYPE_HINT_DIALOG - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - This wizard will help you set up Deluge to your liking. If you are new to Deluge, please note that most of Deluge's functionality and features come in the form of plugins, which can be accessed by clicking on Plugins in the Edit menu or the toolbar. - True - - - GTK_ASSISTANT_PAGE_INTRO - Deluge Configuration - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Deluge needs a range of ports that it will try to listen to for incoming connections. The default ports for bittorrent are 6881-6889, however, most ISPs block those ports, so you're encouraged to pick others, between 49152 and 65535. Alternatively, you can have Deluge automatically pick random ports for you. - True - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - From: - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 0 65535 1 10 10 - - - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - To: - - - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 0 65535 1 10 10 - - - 3 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Use _Random Ports - True - 0 - True - - - - 4 - - - - - 1 - - - - - Deluge Configuration - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Would you like Deluge to automatically download to a predefined location, or would you like to specify the download location every time? - True - - - False - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - False - False - 28 - 1 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Ask where to save each file - 0 - True - True - - - False - False - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Store all downloads in: - 0 - True - True - radio_ask_save - - - - - False - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER - Select A Folder - - - - - 1 - - - - - False - False - 3 - - - - - Deluge Configuration - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Please select the upload speed of your connection, which we will then use to automatically make suggestions for the settings below - True - - - False - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The number of active torrents that Deluge will run. Set to -1 for unlimited. - Maximum Active Torrents: - - - - - 4 - 5 - GTK_EXPAND - GTK_EXPAND - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The maximum upload slots for all torrents. Set -1 for unlimited. - Maximum Upload Slots: - - - - - 3 - 4 - GTK_EXPAND - GTK_EXPAND - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The maximum upload speed for all torrents. Set -1 for unlimited. - Maximum Upload Speed (KiB/s): - - - - - 2 - 3 - GTK_EXPAND - GTK_EXPAND - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The maximum number of connections allowed. Set -1 for unlimited. - Maximum Connections: - - - - - 1 - 2 - GTK_EXPAND - GTK_EXPAND - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The maximum upload slots for all torrents. Set -1 for unlimited. - 0 -1 9000 1 10 10 - - - - - 1 - 2 - 3 - 4 - GTK_EXPAND - GTK_EXPAND - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The maximum upload speed for all torrents. Set -1 for unlimited. - 0 -1 9000 1 10 10 - - - - - 1 - 2 - 2 - 3 - GTK_EXPAND - GTK_EXPAND - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The maximum number of connections allowed. Set -1 for unlimited. - 0 -1 9000 1 10 10 - - - - - 1 - 2 - 1 - 2 - GTK_EXPAND - GTK_EXPAND - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 28.8k -56k -64k -96k -128k -192k -256k -384k -512k -640k -768k -1Mbit -2Mbit -10Mbit -20Mbit -40Mbit -50Mbit -100Mbit - - - - - - 1 - 2 - GTK_EXPAND - GTK_EXPAND - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Your Upload Line Speed: - - - GTK_EXPAND - GTK_EXPAND - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The maximum half-open connections. A high value may crash some cheap routers. Set -1 for unlimited. - Maximum Half-Open Connections: - - - - - 5 - 6 - GTK_EXPAND - GTK_EXPAND - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The maximum half-open connections. A high value may crash some cheap routers. Set -1 for unlimited. - 8 -1 9000 1 10 10 - - - - - 1 - 2 - 5 - 6 - GTK_EXPAND - GTK_EXPAND - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The number of active torrents that Deluge will run. Set to -1 for unlimited. - 0 -1 9000 1 10 10 - - - - - 1 - 2 - 4 - 5 - GTK_EXPAND - GTK_EXPAND - - - - - 1 - - - - - Deluge Configuration - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Help us improve Deluge by sending us your Python and PyGTK -versions, OS and processor types. Absolutely no other -information is sent. - True - 0 - True - True - - - GTK_ASSISTANT_PAGE_CONFIRM - Deluge Configuration - - - - diff --git a/libtorrent/ChangeLog b/libtorrent/ChangeLog new file mode 100644 index 000000000..3c1c6f14b --- /dev/null +++ b/libtorrent/ChangeLog @@ -0,0 +1,216 @@ + * Fixed bug in URL parser that failed to parse IPv6 addresses + * added peer download rate approximation + * added port filter for outgoing connection (to prevent + triggering firewalls) + * made most parameters configurable via session_settings + * added encryption support + * added parole mode for peers whose data fails the hash check. + * optimized heap usage in piece-picker and web seed downloader. + * fixed bug in DHT where older write tokens weren't accepted. + * added support for sparse files. + * introduced speed categories for peers and pieces, to separate + slow and fast peers. + * added a half-open tcp connection limit that takes all connections + in to account, not just peer connections. + * added alerts for filtered IPs. + * added support for SOCKS4 and 5 proxies and HTTP CONNECT proxies. + * fixed proper distributed copies calculation. + * added option to use openssl for sha-1 calculations. + * optimized the piece picker in the case where a peer is a seed. + * added support for local peer discovery + * removed the dependency on the compiled boost.date_time library + * deprecated torrent_info::print() + * added UPnP support + * fixed problem where peer interested flags were not updated correctly + when pieces were filtered + * improvements to ut_pex messages, including support for seed flag + * prioritizes upload bandwidth to peers that might send back data + * the following functions have been deprecated: + void torrent_handle::filter_piece(int index, bool filter) const; + void torrent_handle::filter_pieces(std::vector const& pieces) const; + bool torrent_handle::is_piece_filtered(int index) const; + std::vector torrent_handle::filtered_pieces() const; + void torrent_handle::filter_files(std::vector const& files) const; + + instead, use the piece_priority functions. + + * added support for NAT-PMP + * added support for piece priorities. Piece filtering is now set as + a priority + +release 0.12 + + * fixes to make the DHT more compatible + * http seed improvements including error reporting and url encoding issues. + * fixed bug where directories would be left behind when moving storage + in some cases. + * fixed crashing bug when restarting or stopping the DHT. + * added python binding, using boost.python + * improved character conversion on windows when strings are not utf-8. + * metadata extension now respects the private flag in the torrent. + * made the DHT to only be used as a fallback to trackers by default. + * added support for HTTP redirection support for web seeds. + * fixed race condition when accessing a torrent that was checking its + fast resume data. + * fixed a bug in the DHT which could be triggered if the network was + dropped or extremely rare cases. + * if the download rate is limited, web seeds will now only use left-over + bandwidth after all bt peers have used up as much bandwidth as they can. + * added the possibility to have libtorrent resolve the countries of + the peers in torrents. + * improved the bandwidth limiter (it now implements a leaky bucket/node bucket). + * improved the HTTP seed downloader to report accurate progress. + * added more client peer-id signatures to be recognized. + * added support for HTTP servers that skip the CR before the NL at line breaks. + * fixed bug in the HTTP code that only accepted headers case sensitive. + * fixed bug where one of the session constructors didn't initialize boost.filesystem. + * fixed bug when the initial checking of a torrent fails with an exception. + * fixed bug in DHT code which would send incorrect announce messages. + * fixed bug where the http header parser was case sensitive to the header + names. + * Implemented an optmization which frees the piece_picker once a torrent + turns into a seed. + * Added support for uT peer exchange extension, implemented by Massaroddel. + * Modified the quota management to offer better bandwidth balancing + between peers. + * logging now supports multiple sessions (different sessions now log + to different directories). + * fixed random number generator seed problem, generating the same + peer-id for sessions constructed the same second. + * added an option to accept multiple connections from the same IP. + * improved tracker logging. + * moved the file_pool into session. The number of open files is now + limited per session. + * fixed uninitialized private flag in torrent_info + * fixed long standing issue with file.cpp on windows. Replaced the low level + io functions used on windows. + * made it possible to associate a name with torrents without metadata. + * improved http-downloading performance by requesting entire pieces via + http. + * added plugin interface for extensions. And changed the interface for + enabling extensions. + +release 0.11 + + * added support for incorrectly encoded paths in torrent files + (assumes Latin-1 encoding and converts to UTF-8). + * added support for destructing session objects asynchronously. + * fixed bug with file_progress() with files = 0 bytes + * fixed a race condition bug in udp_tracker_connection that could + cause a crash. + * fixed bug occuring when increasing the sequenced download threshold + with max availability lower than previous threshold. + * fixed an integer overflow bug occuring when built with gcc 4.1.x + * fixed crasing bug when closing while checking a torrent + * fixed bug causing a crash with a torrent with piece length 0 + * added an extension to the DHT network protocol to support the + exchange of nodes with IPv6 addresses. + * modified the ip_filter api slightly to support IPv6 + * modified the api slightly to make sequenced download threshold + a per torrent-setting. + * changed the address type to support IPv6 + * fixed bug in piece picker which would not behave as + expected with regard to sequenced download threshold. + * fixed bug with file_progress() with files > 2 GB. + * added --enable-examples option to configure script. + * fixed problem with the resource distribution algorithm + (controlling e.g upload/download rates). + * fixed incorrect asserts in storage related to torrents with + zero-sized files. + * added support for trackerless torrents (with kademlia DHT). + * support for torrents with the private flag set. + * support for torrents containing bootstrap nodes for the + DHT network. + * fixed problem with the configure script on FreeBSD. + * limits the pipelining used on url-seeds. + * fixed problem where the shutdown always would delay for + session_settings::stop_tracker_timeout seconds. + * session::listen_on() won't reopen the socket in case the port and + interface is the same as the one currently in use. + * added http proxy support for web seeds. + * fixed problem where upload and download stats could become incorrect + in case of high cpu load. + * added more clients to the identifiable list. + * fixed fingerprint parser to cope with latest Mainline versions. + +release 0.10 + + * fixed a bug where the requested number of peers in a tracker request could + be too big. + * fixed a bug where empty files were not created in full allocation mode. + * fixed a bug in storage that would, in rare cases, fail to do a + complete check. + * exposed more settings for tweaking parameters in the piece-picker, + downloader and uploader (http_settings replaced by session_settings). + * tweaked default settings to improve high bandwidth transfers. + * improved the piece picker performance and made it possible to download + popular pieces in sequence to improve disk performance. + * added the possibility to control upload and download limits per peer. + * fixed problem with re-requesting skipped pieces when peer was sending pieces + out of fifo-order. + * added support for http seeding (the GetRight protocol) + * renamed identifiers called 'id' in the public interface to support linking + with Objective.C++ + * changed the extensions protocol to use the new one, which is also + implemented by uTorrent. + * factorized the peer_connection and added web_peer_connection which is + able to download from http-sources. + * converted the network code to use asio (resulted in slight api changes + dealing with network addresses). + * made libtorrent build in vc7 (patches from Allen Zhao) + * fixed bug caused when binding outgoing connections to a non-local interface. + * add_torrent() will now throw if called while the session object is + being closed. + * added the ability to limit the number of simultaneous half-open + TCP connections. Flags in peer_info has been added. + +release 0.9.1 + + * made the session disable file name checks within the boost.filsystem library + * fixed race condition in the sockets + * strings that are invalid utf-8 strings are now decoded with the + local codepage on windows + * added the ability to build libtorrent both as a shared library + * client_test can now monitor a directory for torrent files and automatically + start and stop downloads while running + * fixed problem with file_size() when building on windows with unicode support + * added a new torrent state, allocating + * added a new alert, metadata_failed_alert + * changed the interface to session::add_torrent for some speed optimizations. + * greatly improved the command line control of the example client_test. + * fixed bug where upload rate limit was not being applied. + * files that are being checked will no longer stall files that don't need + checking. + * changed the way libtorrent identifies support for its excentions + to look for 'ext' at the end of the peer-id. + * improved performance by adding a circle buffer for the send buffer. + * fixed bugs in the http tracker connection when using an http proxy. + * fixed problem with storage's file pool when creating torrents and then + starting to seed them. + * hard limit on remote request queue and timeout on requests (a timeout + triggers rerequests). This makes libtorrent work much better with + "broken" clients like BitComet which may ignore requests. + +Initial release 0.9 + + * multitracker support + * serves multiple torrents on a single port and a single thread + * supports http proxies and proxy authentication + * gzipped tracker-responses + * block level piece picker + * queues torrents for file check, instead of checking all of them in parallel + * uses separate threads for checking files and for main downloader + * upload and download rate limits + * piece-wise, unordered, incremental file allocation + * fast resume support + * supports files > 2 gigabytes + * supports the no_peer_id=1 extension + * support for udp-tracker protocol + * number of connections limit + * delays sending have messages + * can resume pieces downloaded in any order + * adjusts the length of the request queue depending on download rate + * supports compact=1 + * selective downloading + * ip filter + diff --git a/libtorrent/NEWS b/libtorrent/NEWS new file mode 100644 index 000000000..cd9658d6b --- /dev/null +++ b/libtorrent/NEWS @@ -0,0 +1,3 @@ + +initial release of libtorrent 0.9 + diff --git a/libtorrent/README b/libtorrent/README new file mode 100644 index 000000000..0b19bf61f --- /dev/null +++ b/libtorrent/README @@ -0,0 +1,25 @@ +libtorrent is a C++ library that aims to be a good alternative to all the +other bittorrent implementations around. It is a +library and not a full featured client, although it comes with a working +example client. + +The main goals of libtorrent are: + + * to be cpu efficient + * to be memory efficient + * to be very easy to use + +See docs/manual.html for more detailed build and usage instructions. + +To build with autotools, run: + + ./configure + +Followed by + + make + +When libtorrent is built, finish off by running the tests: + + make check + diff --git a/libtorrent/bindings/README.txt b/libtorrent/bindings/README.txt new file mode 100644 index 000000000..977ca8c1c --- /dev/null +++ b/libtorrent/bindings/README.txt @@ -0,0 +1,3 @@ +Documentation covering building and using the python binding for libtorrent +is located in the main doc directory. See docs/python_binding.html + diff --git a/libtorrent/bindings/python/src/alert.cpp b/libtorrent/bindings/python/src/alert.cpp new file mode 100755 index 000000000..fe34c6c27 --- /dev/null +++ b/libtorrent/bindings/python/src/alert.cpp @@ -0,0 +1,350 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +using namespace boost::python; +using namespace libtorrent; + +extern char const* alert_doc; +extern char const* alert_msg_doc; +extern char const* alert_severity_doc; +extern char const* torrent_alert_doc; +extern char const* tracker_alert_doc; +extern char const* tracker_error_alert_doc; +extern char const* tracker_warning_alert_doc; +extern char const* tracker_reply_alert_doc; +extern char const* tracker_announce_alert_doc; +extern char const* hash_failed_alert_doc; +extern char const* peer_ban_alert_doc; +extern char const* peer_error_alert_doc; +extern char const* invalid_request_alert_doc; +extern char const* peer_request_doc; +extern char const* torrent_finished_alert_doc; +extern char const* piece_finished_alert_doc; +extern char const* block_finished_alert_doc; +extern char const* block_downloading_alert_doc; +extern char const* storage_moved_alert_doc; +extern char const* torrent_deleted_alert_doc; +extern char const* torrent_paused_alert_doc; +extern char const* torrent_checked_alert_doc; +extern char const* url_seed_alert_doc; +extern char const* file_error_alert_doc; +extern char const* metadata_failed_alert_doc; +extern char const* metadata_received_alert_doc; +extern char const* listen_failed_alert_doc; +extern char const* listen_succeeded_alert_doc; +extern char const* portmap_error_alert_doc; +extern char const* portmap_alert_doc; +extern char const* fastresume_rejected_alert_doc; +extern char const* peer_blocked_alert_doc; +extern char const* scrape_reply_alert_doc; +extern char const* scrape_failed_alert_doc; +extern char const* udp_error_alert_doc; +extern char const* external_ip_alert_doc; +extern char const* save_resume_data_alert_doc; + +void bind_alert() +{ + using boost::noncopyable; + + { + scope alert_scope = class_("alert", alert_doc, no_init) + .def("message", &alert::message, alert_msg_doc) + .def("what", &alert::what) + .def("category", &alert::category) + .def("severity", &alert::severity, alert_severity_doc) + .def("__str__", &alert::message, alert_msg_doc) + ; + + enum_("severity_levels") + .value("debug", alert::debug) + .value("info", alert::info) + .value("warning", alert::warning) + .value("critical", alert::critical) + .value("fatal", alert::fatal) + .value("none", alert::none) + ; + + enum_("category_t") + .value("error_notification", alert::error_notification) + .value("peer_notification", alert::peer_notification) + .value("port_mapping_notification", alert::port_mapping_notification) + .value("storage_notification", alert::storage_notification) + .value("tracker_notification", alert::tracker_notification) + .value("debug_notification", alert::debug_notification) + .value("status_notification", alert::status_notification) + .value("progress_notification", alert::progress_notification) + .value("ip_block_notification", alert::ip_block_notification) + .value("all_categories", alert::all_categories) + ; + } + + class_, noncopyable>( + "torrent_alert", torrent_alert_doc, no_init + ) + .def_readonly("handle", &torrent_alert::handle) + ; + + class_, noncopyable>( + "tracker_alert", tracker_alert_doc, no_init + ) + .def_readonly("url", &tracker_alert::url) + ; + + class_, noncopyable>( + "peer_alert", no_init + ) + .def_readonly("ip", &peer_alert::ip) + .def_readonly("pid", &peer_alert::pid) + ; + class_, noncopyable>( + "tracker_error_alert", tracker_error_alert_doc, no_init + ) + .def_readonly("times_in_row", &tracker_error_alert::times_in_row) + .def_readonly("status_code", &tracker_error_alert::status_code) + ; + + class_, noncopyable>( + "tracker_warning_alert", tracker_warning_alert_doc, no_init + ); + + class_, noncopyable>( + "tracker_reply_alert", tracker_reply_alert_doc, no_init + ) + .def_readonly("num_peers", &tracker_reply_alert::num_peers) + ; + + class_, noncopyable>( + "tracker_announce_alert", tracker_announce_alert_doc, no_init + ); + + class_, noncopyable>( + "hash_failed_alert", hash_failed_alert_doc, no_init + ) + .def_readonly("piece_index", &hash_failed_alert::piece_index) + ; + + class_, noncopyable>( + "peer_ban_alert", peer_ban_alert_doc, no_init + ); + + class_, noncopyable>( + "peer_error_alert", peer_error_alert_doc, no_init + ); + + class_, noncopyable>( + "invalid_request_alert", invalid_request_alert_doc, no_init + ) + .def_readonly("request", &invalid_request_alert::request) + ; + + class_("peer_request", peer_request_doc) + .def_readonly("piece", &peer_request::piece) + .def_readonly("start", &peer_request::start) + .def_readonly("length", &peer_request::length) + .def(self == self) + ; + + class_, noncopyable>( + "torrent_finished_alert", torrent_finished_alert_doc, no_init + ); + + class_, noncopyable>( + "piece_finished_alert", piece_finished_alert_doc, no_init + ) + .def_readonly("piece_index", &piece_finished_alert::piece_index) + ; + + class_, noncopyable>( + "block_finished_alert", block_finished_alert_doc, no_init + ) + .def_readonly("block_index", &block_finished_alert::block_index) + .def_readonly("piece_index", &block_finished_alert::piece_index) + ; + + class_, noncopyable>( + "block_downloading_alert", block_downloading_alert_doc, no_init + ) + .def_readonly("peer_speedmsg", &block_downloading_alert::peer_speedmsg) + .def_readonly("block_index", &block_downloading_alert::block_index) + .def_readonly("piece_index", &block_downloading_alert::piece_index) + ; + + class_, noncopyable>( + "storage_moved_alert", storage_moved_alert_doc, no_init + ); + + class_, noncopyable>( + "torrent_deleted_alert", torrent_deleted_alert_doc, no_init + ); + + class_, noncopyable>( + "torrent_paused_alert", torrent_paused_alert_doc, no_init + ); + + class_, noncopyable>( + "torrent_checked_alert", torrent_checked_alert_doc, no_init + ); + + class_, noncopyable>( + "url_seed_alert", url_seed_alert_doc, no_init + ) + .def_readonly("url", &url_seed_alert::url) + ; + + class_, noncopyable>( + "file_error_alert", file_error_alert_doc, no_init + ) + .def_readonly("file", &file_error_alert::file) + ; + + class_, noncopyable>( + "metadata_failed_alert", metadata_failed_alert_doc, no_init + ); + + class_, noncopyable>( + "metadata_received_alert", metadata_received_alert_doc, no_init + ); + + class_, noncopyable>( + "listen_failed_alert", listen_failed_alert_doc, no_init + ); + + class_, noncopyable>( + "listen_succeeded_alert", listen_succeeded_alert_doc, no_init + ) + .def_readonly("endpoint", &listen_succeeded_alert::endpoint) + ; + + class_, noncopyable>( + "portmap_error_alert", portmap_error_alert_doc, no_init + ) + .def_readonly("mapping", &portmap_error_alert::mapping) + .def_readonly("type", &portmap_error_alert::type) + ; + + class_, noncopyable>( + "portmap_alert", portmap_alert_doc, no_init + ) + .def_readonly("mapping", &portmap_alert::mapping) + .def_readonly("external_port", &portmap_alert::external_port) + .def_readonly("type", &portmap_alert::type) + ; + + class_, noncopyable>( + "fastresume_rejected_alert", fastresume_rejected_alert_doc, no_init + ); + + class_, noncopyable>( + "peer_blocked_alert", peer_blocked_alert_doc, no_init + ) + .def_readonly("ip", &peer_blocked_alert::ip) + ; + + class_, noncopyable>( + "scrape_reply_alert", scrape_reply_alert_doc, no_init + ) + .def_readonly("incomplete", &scrape_reply_alert::incomplete) + .def_readonly("complete", &scrape_reply_alert::complete) + ; + + class_, noncopyable>( + "scrape_failed_alert", scrape_failed_alert_doc, no_init + ); + + class_, noncopyable>( + "udp_error_alert", udp_error_alert_doc, no_init + ) + .def_readonly("endpoint", &udp_error_alert::endpoint) + ; + + class_, noncopyable>( + "external_ip_alert", external_ip_alert_doc, no_init + ) + .def_readonly("external_address", &external_ip_alert::external_address) + ; + + class_, noncopyable>( + "save_resume_data_alert", save_resume_data_alert_doc, no_init + ) + .def_readonly("resume_data", &save_resume_data_alert::resume_data) + ; + + class_, noncopyable>( + "file_renamed_alert", no_init + ) + .def_readonly("name", &file_renamed_alert::name) + ; + + class_, noncopyable>( + "file_rename_failed_alert", no_init + ) + .def_readonly("index", &file_rename_failed_alert::index) + ; + + class_, noncopyable>( + "torrent_resumed_alert", no_init + ); + + class_, noncopyable>( + "state_changed_alert", no_init + ) + .def_readonly("state", &state_changed_alert::state) + ; + + class_, noncopyable>( + "dht_reply_alert", no_init + ) + .def_readonly("num_peers", &dht_reply_alert::num_peers) + ; + + class_, noncopyable>( + "peer_unsnubbed_alert", no_init + ); + + class_, noncopyable>( + "peer_snubbed_alert", no_init + ); + + class_, noncopyable>( + "peer_connect_alert", no_init + ); + + class_, noncopyable>( + "peer_disconnected_alert", no_init + ); + + class_, noncopyable>( + "request_dropped_alert", no_init + ) + .def_readonly("block_index", &request_dropped_alert::block_index) + .def_readonly("piece_index", &request_dropped_alert::piece_index) + ; + + class_, noncopyable>( + "block_timeout_alert", no_init + ) + .def_readonly("block_index", &block_timeout_alert::block_index) + .def_readonly("piece_index", &block_timeout_alert::piece_index) + ; + + class_, noncopyable>( + "unwanted_block_alert", no_init + ) + .def_readonly("block_index", &unwanted_block_alert::block_index) + .def_readonly("piece_index", &unwanted_block_alert::piece_index) + ; + + class_, noncopyable>( + "torrent_delete_failed_alert", no_init + ); + + class_, noncopyable>( + "save_resume_data_failed_alert", no_init + ); + +} diff --git a/libtorrent/bindings/python/src/big_number.cpp b/libtorrent/bindings/python/src/big_number.cpp new file mode 100755 index 000000000..4e41df521 --- /dev/null +++ b/libtorrent/bindings/python/src/big_number.cpp @@ -0,0 +1,20 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +void bind_big_number() +{ + using namespace boost::python; + using namespace libtorrent; + + class_("big_number") + .def(self == self) + .def(self != self) + .def(self < self) + .def(self_ns::str(self)) + ; +} + diff --git a/libtorrent/bindings/python/src/converters.cpp b/libtorrent/bindings/python/src/converters.cpp new file mode 100755 index 000000000..f684cc4f3 --- /dev/null +++ b/libtorrent/bindings/python/src/converters.cpp @@ -0,0 +1,5 @@ +// Copyright Daniel Wallin 2007. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + diff --git a/libtorrent/bindings/python/src/datetime.cpp b/libtorrent/bindings/python/src/datetime.cpp new file mode 100755 index 000000000..da1347671 --- /dev/null +++ b/libtorrent/bindings/python/src/datetime.cpp @@ -0,0 +1,81 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "optional.hpp" +#include + +using namespace boost::python; + +#if BOOST_VERSION < 103400 + +// From Boost 1.34 +object import(str name) +{ + // should be 'char const *' but older python versions don't use 'const' yet. + char *n = extract(name); + handle<> module(borrowed(PyImport_ImportModule(n))); + return object(module); +} + +#endif + +object datetime_timedelta; +object datetime_datetime; + +struct time_duration_to_python +{ + static PyObject* convert(boost::posix_time::time_duration const& d) + { + object result = datetime_timedelta( + 0 // days + , 0 // seconds + , d.total_microseconds() + ); + + return incref(result.ptr()); + } +}; + +struct ptime_to_python +{ + static PyObject* convert(boost::posix_time::ptime const& pt) + { + boost::gregorian::date date = pt.date(); + boost::posix_time::time_duration td = pt.time_of_day(); + + object result = datetime_datetime( + (int)date.year() + , (int)date.month() + , (int)date.day() + , td.hours() + , td.minutes() + , td.seconds() + ); + + return incref(result.ptr()); + } +}; + +void bind_datetime() +{ + object datetime = import("datetime").attr("__dict__"); + + datetime_timedelta = datetime["timedelta"]; + datetime_datetime = datetime["datetime"]; + + to_python_converter< + boost::posix_time::time_duration + , time_duration_to_python + >(); + + to_python_converter< + boost::posix_time::ptime + , ptime_to_python + >(); + + optional_to_python(); +} + diff --git a/libtorrent/bindings/python/src/docstrings.cpp b/libtorrent/bindings/python/src/docstrings.cpp new file mode 100755 index 000000000..b1d28670d --- /dev/null +++ b/libtorrent/bindings/python/src/docstrings.cpp @@ -0,0 +1,354 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// -- torrent_status -------------------------------------------------------- + +char const* torrent_status_doc = + "Represents the current status for a torrent.\n" + "Returned by `torrent_handle.status()`."; + +char const* torrent_status_state_doc = + "The torrents current task. One of `torrent_status.states`."; + +char const* torrent_status_paused_doc = + "Indicates if this torrent is paused or not."; + +char const* torrent_status_progress_doc = + "A value in the range [0, 1], that represents the progress of\n" + "the torrent's current task."; + +char const* torrent_status_next_announce_doc = + "The time until the torrent will announce itself to the\n" + "tracker. An instance of `datetime.timedelta`."; + +char const* torrent_status_announce_interval_doc = + "The interval at which the torrent will reannounce itself to the\n" + "tracker. An instance of `datetime.timedelta`."; + +char const* torrent_status_current_tracker_doc = + "The URL of the last working tracker. If no tracker request has\n" + "been successful yet, it's set to an empty string."; + +char const* torrent_status_total_download_doc = ""; +char const* torrent_status_total_upload_doc = ""; +char const* torrent_status_total_payload_download_doc = ""; +char const* torrent_status_total_payload_upload_doc = ""; +char const* torrent_status_total_failed_bytes_doc = ""; + +// -- session_status -------------------------------------------------------- + +char const* session_status_doc = + ""; +char const* session_status_has_incoming_connections_doc = + ""; +char const* session_status_upload_rate_doc = + ""; +char const* session_status_download_rate_doc = + ""; +char const* session_status_payload_upload_rate_doc = + ""; +char const* session_status_payload_download_rate_doc = + ""; +char const* session_status_total_download_doc = + ""; +char const* session_status_total_upload_doc = + ""; +char const* session_status_total_payload_download_doc = + ""; +char const* session_status_total_payload_upload_doc = + ""; +char const* session_status_num_peers_doc = + ""; +char const* session_status_dht_nodes_doc = + ""; +char const* session_status_cache_nodes_doc = + ""; +char const* session_status_dht_torrents_doc = + ""; + +// -- session --------------------------------------------------------------- + +char const* session_doc = + ""; +char const* session_init_doc = + "The `fingerprint` is a short string that will be used in\n" + "the peer-id to identify the client and the client's version.\n" + "For more details see the `fingerprint` class.\n" + "The constructor that only takes a fingerprint will not open\n" + "a listen port for the session, to get it running you'll have\n" + "to call `session.listen_on()`."; + +char const* session_listen_on_doc = + ""; +char const* session_is_listening_doc = + ""; +char const* session_listen_port_doc = + ""; + +char const* session_status_m_doc = + "Returns an instance of `session_status` with session wide-statistics\n" + "and status"; + +char const* session_start_dht_doc = + ""; +char const* session_stop_dht_doc = + ""; +char const* session_dht_state_doc = + ""; +char const* session_add_dht_router_doc = + "add dht router"; + +char const* session_add_torrent_doc = + "Adds a new torrent to the session. Return a `torrent_handle`.\n" + "\n" + ":Parameters:\n" + " - `torrent_info`: `torrent_info` instance representing the torrent\n" + " you want to add.\n" + " - `save_path`: The path to the directory where files will be saved.\n" + " - `resume_data (optional)`: The resume data for this torrent, as decoded\n" + " with `bdecode()`. This can be acquired from a running torrent with\n" + " `torrent_handle.write_resume_data()`.\n" + " - `compact_mode (optional)`: If set to true (default), the storage\n" + " will grow as more pieces are downloaded, and pieces are rearranged\n" + " to finally be in their correct places once the entire torrent has\n" + " been downloaded. If it is false, the entire storage is allocated\n" + " before download begins. I.e. the files contained in the torrent\n" + " are filled with zeros, and each downloaded piece is put in its\n" + " final place directly when downloaded.\n" + " - `block_size (optional)`: Sets the preferred request size, i.e.\n" + " the number of bytes to request from a peer at a time. This block size\n" + " must be a divisor of the piece size, and since the piece size is an\n" + " even power of 2, so must the block size be. If the block size given\n" + " here turns out to be greater than the piece size, it will simply be\n" + " clamped to the piece size.\n" + "\n" + ":Exceptions:\n" + " - `duplicate_torrent`: If the torrent you are trying to add already\n" + " exists in the session (is either queued for checking, being checked\n" + " or downloading) `add_torrent()` will throw `duplicate_torrent`.\n"; + +char const* session_remove_torrent_doc = + "Close all peer connections associated with the torrent and tell the\n" + "tracker that we've stopped participating in the swarm."; + +char const* session_download_rate_limit_doc = + ""; +char const* session_upload_rate_limit_doc = + ""; +char const* session_set_download_rate_limit_doc = + ""; +char const* session_set_upload_rate_limit_doc = + ""; +char const* session_set_max_uploads_doc = + ""; +char const* session_set_max_connections_doc = + ""; +char const* session_set_max_half_open_connections_doc = + "Sets the maximum number of half-open connections libtorrent will\n" + "have when connecting to peers. A half-open connection is one where\n" + "connect() has been called, but the connection still hasn't been\n" + "established (nor failed). Windows XP Service Pack 2 sets a default,\n" + "system wide, limit of the number of half-open connections to 10. So, \n" + "this limit can be used to work nicer together with other network\n" + "applications on that system. The default is to have no limit, and passing\n" + "-1 as the limit, means to have no limit. When limiting the number of\n" + "simultaneous connection attempts, peers will be put in a queue waiting\n" + "for their turn to get connected."; +char const* session_num_connections_doc = + ""; +char const* session_set_settings_doc = + ""; +char const* session_set_pe_settings_doc = + ""; +char const* session_get_pe_settings_doc = + ""; +char const* session_set_severity_level_doc = + ""; +char const* session_pop_alert_doc = + ""; +char const* session_start_upnp_doc = + ""; +char const* session_stop_upnp_doc = + ""; +char const* session_start_lsd_doc = + ""; +char const* session_stop_lsd_doc = + ""; +char const* session_start_natpmp_doc = + ""; +char const* session_stop_natpmp_doc = + ""; +char const* session_set_ip_filter_doc = + ""; + +// -- alert ----------------------------------------------------------------- + +char const* alert_doc = + "Base class for all concrete alert classes."; + +char const* alert_msg_doc = + "Returns a string describing this alert."; + +char const* alert_severity_doc = + "Returns the severity level for this alert, one of `alert.severity_levels`."; + +char const* torrent_alert_doc = + ""; + +char const* tracker_alert_doc = + "This alert is generated on tracker time outs, premature\n" + "disconnects, invalid response or a HTTP response other than\n" + "\"200 OK\". From the alert you can get the handle to the torrent\n" + "the tracker belongs to. This alert is generated as severity level\n" + "`alert.severity_levels.warning`."; + +char const* tracker_error_alert_doc = + ""; + +char const* tracker_warning_alert_doc = + "This alert is triggered if the tracker reply contains a warning\n" + "field. Usually this means that the tracker announce was successful\n" + ", but the tracker has a message to the client. The message string in\n" + "the alert will contain the warning message from the tracker. It is\n" + "generated with severity level `alert.severity_levels.warning`."; + +char const* tracker_reply_alert_doc = + "This alert is only for informational purpose. It is generated when\n" + "a tracker announce succeeds. It is generated with severity level\n" + "`alert.severity_levels.info`."; + +char const* tracker_announce_alert_doc = + "This alert is generated each time a tracker announce is sent\n" + "(or attempted to be sent). It is generated at severity level `alert.severity_levels.info`."; + +char const* hash_failed_alert_doc = + "This alert is generated when a finished piece fails its hash check.\n" + "You can get the handle to the torrent which got the failed piece\n" + "and the index of the piece itself from the alert. This alert is\n" + "generated as severity level `alert.severity_levels.info`."; + +char const* peer_ban_alert_doc = + "This alert is generated when a peer is banned because it has sent\n" + "too many corrupt pieces to us. It is generated at severity level\n" + "`alert.severity_levels.info`. The handle member is a `torrent_handle` to the torrent that\n" + "this peer was a member of."; + +char const* peer_error_alert_doc = + "This alert is generated when a peer sends invalid data over the\n" + "peer-peer protocol. The peer will be disconnected, but you get its\n" + "ip address from the alert, to identify it. This alert is generated\n" + "is severity level `alert.severity_levels.debug`."; + +char const* invalid_request_alert_doc = + "This is a debug alert that is generated by an incoming invalid\n" + "piece request. The handle is a handle to the torrent the peer\n" + "is a member of. Ip is the address of the peer and the request is\n" + "the actual incoming request from the peer. The alert is generated\n" + "as severity level `alert.severity_levels.debug`."; + +char const* peer_request_doc = + "The `peer_request` contains the values the client sent in its\n" + "request message. ``piece`` is the index of the piece it want data\n" + "from, ``start`` is the offset within the piece where the data should be\n" + "read, and ``length`` is the amount of data it wants."; + +char const* torrent_finished_alert_doc = + "This alert is generated when a torrent switches from being a\n" + "downloader to a seed. It will only be generated once per torrent.\n" + "It contains a `torrent_handle` to the torrent in question. This alert\n" + "is generated as severity level `alert.severity_levels.info`."; + +char const* piece_finished_alert_doc = + ""; + +char const* block_finished_alert_doc = + ""; + +char const* block_downloading_alert_doc = + ""; + +char const* storage_moved_alert_doc = + "This alert is generated when a torrent moves storage.\n" + "It contains a `torrent_handle` to the torrent in question. This alert\n" + "is generated as severity level `alert.severity_levels.warning`."; + +char const* torrent_deleted_alert_doc = + ""; + +char const* torrent_paused_alert_doc = + "This alert is generated when a torrent switches from being a\n" + "active to paused.\n" + "It contains a `torrent_handle` to the torrent in question. This alert\n" + "is generated as severity level `alert.severity_levels.warning`."; + +char const* torrent_checked_alert_doc = + ""; + +char const* url_seed_alert_doc = + "This alert is generated when a HTTP seed name lookup fails. This\n" + "alert is generated as severity level `alert.severity_levels.warning`."; + +char const* file_error_alert_doc = + "If the storage fails to read or write files that it needs access\n" + "to, this alert is generated and the torrent is paused. It is\n" + "generated as severity level `alert.severity_levels.fatal`."; + +char const* metadata_failed_alert_doc = + "This alert is generated when the metadata has been completely\n" + "received and the info-hash failed to match it. i.e. the\n" + "metadata that was received was corrupt. libtorrent will\n" + "automatically retry to fetch it in this case. This is only\n" + "relevant when running a torrent-less download, with the metadata\n" + "extension provided by libtorrent. It is generated at severity\n" + "level `alert.severity_levels.info`."; + +char const* metadata_received_alert_doc = + "This alert is generated when the metadata has been completely\n" + "received and the torrent can start downloading. It is not generated\n" + "on torrents that are started with metadata, but only those that\n" + "needs to download it from peers (when utilizing the libtorrent\n" + "extension). It is generated at severity level `alert.severity_levels.info`."; + +char const* listen_failed_alert_doc = + "This alert is generated when none of the ports, given in the\n" + "port range, to `session` can be opened for listening. This alert\n" + "is generated as severity level `alert.severity_levels.fatal`."; + +char const* listen_succeeded_alert_doc = + ""; + +char const* portmap_error_alert_doc = + ""; + +char const* portmap_alert_doc = + ""; + +char const* fastresume_rejected_alert_doc = + "This alert is generated when a fastresume file has been passed\n" + "to `session.add_torrent` but the files on disk did not match the\n" + "fastresume file. The string explains the reason why the resume\n" + "file was rejected. It is generated at severity level `alert.severity_levels.warning`."; + +char const* peer_blocked_alert_doc = + ""; + +char const* scrape_reply_alert_doc = + "This alert is generated when a scrape request succeeds.\n" + "incomplete and complete is the data returned in the scrape\n" + "response. These numbers may be -1 if the reponse was malformed."; + +char const* scrape_failed_alert_doc = + "If a scrape request fails, this alert is generated. This might\n" + "be due to the tracker timing out, refusing connection or returning\n" + "an http response code indicating an error."; + +char const* udp_error_alert_doc = + ""; + +char const* external_ip_alert_doc = + ""; + +char const* save_resume_data_alert_doc = + ""; + diff --git a/libtorrent/bindings/python/src/entry.cpp b/libtorrent/bindings/python/src/entry.cpp new file mode 100755 index 000000000..b24f6a2cf --- /dev/null +++ b/libtorrent/bindings/python/src/entry.cpp @@ -0,0 +1,132 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::python; +using namespace libtorrent; + +struct entry_to_python +{ + static object convert(entry::list_type const& l) + { + list result; + + for (entry::list_type::const_iterator i(l.begin()), e(l.end()); i != e; ++i) + { + result.append(*i); + } + + return result; + } + + static object convert(entry::dictionary_type const& d) + { + dict result; + + for (entry::dictionary_type::const_iterator i(d.begin()), e(d.end()); i != e; ++i) + result[i->first] = i->second; + + return result; + } + + static object convert0(entry const& e) + { + switch (e.type()) + { + case entry::int_t: + return object(e.integer()); + case entry::string_t: + return object(e.string()); + case entry::list_t: + return convert(e.list()); + case entry::dictionary_t: + return convert(e.dict()); + default: + return object(); + } + } + + static PyObject* convert(entry const& e) + { + return incref(convert0(e).ptr()); + } +}; + +struct entry_from_python +{ + entry_from_python() + { + converter::registry::push_back( + &convertible, &construct, type_id() + ); + } + + static void* convertible(PyObject* e) + { + return e; + } + + static entry construct0(object e) + { + if (extract(e).check()) + { + dict d = extract(e); + list items(d.items()); + std::size_t length = extract(items.attr("__len__")()); + entry result(entry::dictionary_t); + + for (std::size_t i = 0; i < length; ++i) + { + result.dict().insert( + std::make_pair( + extract(items[i][0])() + , construct0(items[i][1]) + ) + ); + } + + return result; + } + else if (extract(e).check()) + { + list l = extract(e); + + std::size_t length = extract(l.attr("__len__")()); + entry result(entry::list_t); + + for (std::size_t i = 0; i < length; ++i) + { + result.list().push_back(construct0(l[i])); + } + + return result; + } + else if (extract(e).check()) + { + return entry(extract(e)()); + } + else if (extract(e).check()) + { + return entry(extract(e)()); + } + + return entry(); + } + + static void construct(PyObject* e, converter::rvalue_from_python_stage1_data* data) + { + void* storage = ((converter::rvalue_from_python_storage*)data)->storage.bytes; + new (storage) entry(construct0(object(borrowed(e)))); + data->convertible = storage; + } +}; + +void bind_entry() +{ + to_python_converter(); + entry_from_python(); +} + diff --git a/libtorrent/bindings/python/src/extensions.cpp b/libtorrent/bindings/python/src/extensions.cpp new file mode 100755 index 000000000..acb8f2457 --- /dev/null +++ b/libtorrent/bindings/python/src/extensions.cpp @@ -0,0 +1,159 @@ +// Copyright Daniel Wallin, Arvid Norberg 2007. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include +#include "gil.hpp" + +using namespace boost::python; +using namespace libtorrent; + +namespace +{ + + struct torrent_plugin_wrap : torrent_plugin, wrapper + { + boost::shared_ptr new_connection(peer_connection* p) + { + lock_gil lock; + + if (override f = this->get_override("new_connection")) + return f(ptr(p)); + return torrent_plugin::new_connection(p); + } + + boost::shared_ptr default_new_connection(peer_connection* p) + { + return this->torrent_plugin::new_connection(p); + } + + void on_piece_pass(int index) + { + lock_gil lock; + + if (override f = this->get_override("on_piece_pass")) + f(index); + else + torrent_plugin::on_piece_pass(index); + } + + void default_on_piece_pass(int index) + { + this->torrent_plugin::on_piece_pass(index); + } + + void on_piece_failed(int index) + { + lock_gil lock; + + if (override f = this->get_override("on_piece_failed")) + f(index); + else + torrent_plugin::on_piece_failed(index); + } + + void default_on_piece_failed(int index) + { + return this->torrent_plugin::on_piece_failed(index); + } + + void tick() + { + lock_gil lock; + + if (override f = this->get_override("tick")) + f(); + else + torrent_plugin::tick(); + } + + void default_tick() + { + return this->torrent_plugin::tick(); + } + + bool on_pause() + { + lock_gil lock; + + if (override f = this->get_override("on_pause")) + return f(); + return torrent_plugin::on_pause(); + } + + bool default_on_pause() + { + return this->torrent_plugin::on_pause(); + } + + bool on_resume() + { + lock_gil lock; + + if (override f = this->get_override("on_resume")) + return f(); + return torrent_plugin::on_resume(); + } + + bool default_on_resume() + { + return this->torrent_plugin::on_resume(); + } + }; + +} // namespace unnamed + + +boost::shared_ptr create_metadata_plugin_wrapper(torrent* t) { + return create_metadata_plugin(t, NULL); +} + +boost::shared_ptr create_ut_pex_plugin_wrapper(torrent* t) { + return create_ut_pex_plugin(t, NULL); +} + +void bind_extensions() +{ + class_< + torrent_plugin_wrap, boost::shared_ptr, boost::noncopyable + >("torrent_plugin") + .def( + "new_connection" + , &torrent_plugin::new_connection, &torrent_plugin_wrap::default_new_connection + ) + .def( + "on_piece_pass" + , &torrent_plugin::on_piece_pass, &torrent_plugin_wrap::default_on_piece_pass + ) + .def( + "on_piece_failed" + , &torrent_plugin::on_piece_failed, &torrent_plugin_wrap::default_on_piece_failed + ) + .def( + "tick" + , &torrent_plugin::tick, &torrent_plugin_wrap::default_tick + ) + .def( + "on_pause" + , &torrent_plugin::on_pause, &torrent_plugin_wrap::default_on_pause + ) + .def( + "on_resume" + , &torrent_plugin::on_resume, &torrent_plugin_wrap::default_on_resume + ); + + // TODO move to it's own file + class_("peer_connection", no_init); + + class_ >("torrent_plugin", no_init); + def("create_ut_pex_plugin", create_ut_pex_plugin_wrapper); + def("create_metadata_plugin", create_metadata_plugin_wrapper); +} + + diff --git a/libtorrent/bindings/python/src/filesystem.cpp b/libtorrent/bindings/python/src/filesystem.cpp new file mode 100755 index 000000000..3c5badb8e --- /dev/null +++ b/libtorrent/bindings/python/src/filesystem.cpp @@ -0,0 +1,51 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::python; + +struct path_to_python +{ + static PyObject* convert(boost::filesystem::path const& p) + { + return incref(object(p.string()).ptr()); + } +}; + +struct path_from_python +{ + path_from_python() + { + converter::registry::push_back( + &convertible, &construct, type_id() + ); + } + + static void* convertible(PyObject* x) + { + return PyString_Check(x) ? x : 0; + } + + static void construct(PyObject* x, converter::rvalue_from_python_stage1_data* data) + { + void* storage = ((converter::rvalue_from_python_storage< + boost::filesystem::path + >*)data)->storage.bytes; + new (storage) boost::filesystem::path(PyString_AsString(x)); + data->convertible = storage; + } +}; + +void bind_filesystem() +{ + to_python_converter(); + path_from_python(); + + using namespace boost::filesystem; + if (path::default_name_check_writable()) + path::default_name_check(no_check); +} + diff --git a/libtorrent/bindings/python/src/fingerprint.cpp b/libtorrent/bindings/python/src/fingerprint.cpp new file mode 100755 index 000000000..ca40f3d4d --- /dev/null +++ b/libtorrent/bindings/python/src/fingerprint.cpp @@ -0,0 +1,27 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +void bind_fingerprint() +{ + using namespace boost::python; + using namespace libtorrent; + + class_("fingerprint", no_init) + .def( + init( + (arg("id"), "major", "minor", "revision", "tag") + ) + ) + .def("__str__", &fingerprint::to_string) + .def_readonly("name", &fingerprint::name) + .def_readonly("major_version", &fingerprint::major_version) + .def_readonly("minor_version", &fingerprint::minor_version) + .def_readonly("revision_version", &fingerprint::revision_version) + .def_readonly("tag_version", &fingerprint::tag_version) + ; +} + diff --git a/libtorrent/bindings/python/src/gil.hpp b/libtorrent/bindings/python/src/gil.hpp new file mode 100755 index 000000000..d9534c92c --- /dev/null +++ b/libtorrent/bindings/python/src/gil.hpp @@ -0,0 +1,144 @@ +// Copyright Daniel Wallin 2007. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef GIL_070107_HPP +# define GIL_070107_HPP + +# include +# include +# include +# include + +//namespace libtorrent { namespace python { + +// RAII helper to release GIL. +struct allow_threading_guard +{ + allow_threading_guard() + : save(PyEval_SaveThread()) + {} + + ~allow_threading_guard() + { + PyEval_RestoreThread(save); + } + + PyThreadState* save; +}; + +struct lock_gil +{ + lock_gil() + : state(PyGILState_Ensure()) + {} + + ~lock_gil() + { + PyGILState_Release(state); + } + + PyGILState_STATE state; +}; + +template +struct allow_threading +{ + allow_threading(F fn) + : fn(fn) + {} + + template + R operator()(A0& a0) + { + allow_threading_guard guard; + return (a0.*fn)(); + } + + template + R operator()(A0& a0, A1& a1) + { + allow_threading_guard guard; + return (a0.*fn)(a1); + } + + template + R operator()(A0& a0, A1& a1, A2& a2) + { + allow_threading_guard guard; + return (a0.*fn)(a1,a2); + } + + template + R operator()(A0& a0, A1& a1, A2& a2, A3& a3) + { + allow_threading_guard guard; + return (a0.*fn)(a1,a2,a3); + } + + template + R operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) + { + allow_threading_guard guard; + return (a0.*fn)(a1,a2,a3,a4); + } + + template + R operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) + { + allow_threading_guard guard; + return (a0.*fn)(a1,a2,a3,a4,a5); + } + + F fn; +}; + +template +struct visitor : boost::python::def_visitor > +{ + visitor(F fn) + : fn(fn) + {} + + template + void visit_aux( + Class& cl, char const* name + , Options const& options, Signature const& signature) const + { + typedef typename boost::mpl::at_c::type return_type; + + cl.def( + name + , boost::python::make_function( + allow_threading(fn) + , options.policies() + , options.keywords() + , signature + ) + ); + } + + template + void visit(Class& cl, char const* name, Options const& options) const + { + this->visit_aux( + cl, name, options + , boost::python::detail::get_signature(fn, (typename Class::wrapped_type*)0) + ); + } + + F fn; +}; + +// Member function adaptor that releases and aqcuires the GIL +// around the function call. +template +visitor allow_threads(F fn) +{ + return visitor(fn); +} + +//}} // namespace libtorrent::python + +#endif // GIL_070107_HPP + diff --git a/libtorrent/bindings/python/src/ip_filter.cpp b/libtorrent/bindings/python/src/ip_filter.cpp new file mode 100644 index 000000000..eed216141 --- /dev/null +++ b/libtorrent/bindings/python/src/ip_filter.cpp @@ -0,0 +1,28 @@ +// Copyright Andrew Resch 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "gil.hpp" + +using namespace boost::python; +using namespace libtorrent; + +namespace +{ + void add_rule(ip_filter& filter, std::string start, std::string end, int flags) + { + return filter.add_rule(address_v4::from_string(start), address_v4::from_string(end), flags); + } +} + +void bind_ip_filter() +{ + class_("ip_filter") + .def("add_rule", &add_rule) + .def("access", allow_threads(&ip_filter::access)) + .def_readonly("export_filter", allow_threads(&ip_filter::export_filter)) + ; +} + diff --git a/libtorrent/bindings/python/src/module.cpp b/libtorrent/bindings/python/src/module.cpp new file mode 100755 index 000000000..ea718388e --- /dev/null +++ b/libtorrent/bindings/python/src/module.cpp @@ -0,0 +1,50 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +void bind_utility(); +void bind_fingerprint(); +void bind_big_number(); +void bind_session(); +void bind_entry(); +void bind_torrent_info(); +void bind_filesystem(); +void bind_torrent_handle(); +void bind_torrent_status(); +void bind_session_settings(); +void bind_version(); +void bind_alert(); +void bind_datetime(); +void bind_extensions(); +void bind_peer_plugin(); +void bind_torrent(); +void bind_peer_info(); +void bind_ip_filter(); + +BOOST_PYTHON_MODULE(libtorrent) +{ + Py_Initialize(); + PyEval_InitThreads(); + + bind_utility(); + bind_fingerprint(); + bind_big_number(); + bind_entry(); + bind_session(); + bind_torrent_info(); + bind_filesystem(); + bind_torrent_handle(); + bind_torrent_status(); + bind_session_settings(); + bind_version(); + bind_alert(); + bind_datetime(); + bind_extensions(); + bind_peer_plugin(); + bind_torrent(); + bind_peer_info(); + bind_ip_filter(); +} + diff --git a/libtorrent/bindings/python/src/optional.hpp b/libtorrent/bindings/python/src/optional.hpp new file mode 100755 index 000000000..63138cc68 --- /dev/null +++ b/libtorrent/bindings/python/src/optional.hpp @@ -0,0 +1,31 @@ +// Copyright Daniel Wallin 2007. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef OPTIONAL_070108_HPP +# define OPTIONAL_070108_HPP + +# include +# include + +template +struct optional_to_python +{ + optional_to_python() + { + boost::python::to_python_converter< + boost::optional, optional_to_python + >(); + } + + static PyObject* convert(boost::optional const& x) + { + if (!x) + return boost::python::incref(Py_None); + + return boost::python::incref(boost::python::object(*x).ptr()); + } +}; + +#endif // OPTIONAL_070108_HPP + diff --git a/libtorrent/bindings/python/src/peer_info.cpp b/libtorrent/bindings/python/src/peer_info.cpp new file mode 100755 index 000000000..9ceeead7a --- /dev/null +++ b/libtorrent/bindings/python/src/peer_info.cpp @@ -0,0 +1,128 @@ +// Copyright Daniel Wallin 2007. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include + +using namespace boost::python; +using namespace libtorrent; + +int get_last_active(peer_info const& pi) +{ + return total_seconds(pi.last_active); +} + +int get_last_request(peer_info const& pi) +{ + return total_seconds(pi.last_request); +} + +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES +str get_country(peer_info const& pi) +{ + return str(pi.country, 2); +} +#endif + +tuple get_ip(peer_info const& pi) +{ + return make_tuple(boost::lexical_cast(pi.ip.address()), pi.ip.port()); +} + +list get_pieces(peer_info const& pi) +{ + list ret; + + for (bitfield::const_iterator i = pi.pieces.begin() + , end(pi.pieces.end()); i != end; ++i) + { + ret.append(*i); + } + return ret; +} + +void bind_peer_info() +{ + scope pi = class_("peer_info") + .def_readonly("flags", &peer_info::flags) + .def_readonly("source", &peer_info::source) + .def_readonly("read_state", &peer_info::read_state) + .def_readonly("write_state", &peer_info::write_state) + .add_property("ip", get_ip) + .def_readonly("up_speed", &peer_info::up_speed) + .def_readonly("down_speed", &peer_info::down_speed) + .def_readonly("payload_up_speed", &peer_info::payload_up_speed) + .def_readonly("payload_down_speed", &peer_info::payload_down_speed) + .def_readonly("total_download", &peer_info::total_download) + .def_readonly("total_upload", &peer_info::total_upload) + .def_readonly("pid", &peer_info::pid) + .add_property("pieces", get_pieces) + .def_readonly("upload_limit", &peer_info::upload_limit) + .def_readonly("download_limit", &peer_info::download_limit) + .add_property("last_request", get_last_request) + .add_property("last_active", get_last_active) + .def_readonly("send_buffer_size", &peer_info::send_buffer_size) + .def_readonly("used_send_buffer", &peer_info::used_send_buffer) + .def_readonly("num_hashfails", &peer_info::num_hashfails) +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + .add_property("country", get_country) +#endif +#ifndef TORRENT_DISABLE_GEO_IP + .def_readonly("inet_as_name", &peer_info::inet_as_name) + .def_readonly("inet_as", &peer_info::inet_as) +#endif + .def_readonly("load_balancing", &peer_info::load_balancing) + .def_readonly("download_queue_length", &peer_info::download_queue_length) + .def_readonly("upload_queue_length", &peer_info::upload_queue_length) + .def_readonly("failcount", &peer_info::failcount) + .def_readonly("downloading_piece_index", &peer_info::downloading_piece_index) + .def_readonly("downloading_block_index", &peer_info::downloading_block_index) + .def_readonly("downloading_progress", &peer_info::downloading_progress) + .def_readonly("downloading_total", &peer_info::downloading_total) + .def_readonly("client", &peer_info::client) + .def_readonly("connection_type", &peer_info::connection_type) + .def_readonly("remote_dl_rate", &peer_info::remote_dl_rate) + .def_readonly("pending_disk_bytes", &peer_info::pending_disk_bytes) + .def_readonly("send_quota", &peer_info::send_quota) + .def_readonly("receive_quota", &peer_info::receive_quota) + .def_readonly("rtt", &peer_info::rtt) + ; + + // flags + pi.attr("interesting") = (int)peer_info::interesting; + pi.attr("choked") = (int)peer_info::choked; + pi.attr("remote_interested") = (int)peer_info::remote_interested; + pi.attr("remote_choked") = (int)peer_info::remote_choked; + pi.attr("supports_extensions") = (int)peer_info::supports_extensions; + pi.attr("local_connection") = (int)peer_info::local_connection; + pi.attr("handshake") = (int)peer_info::handshake; + pi.attr("connecting") = (int)peer_info::connecting; + pi.attr("queued") = (int)peer_info::queued; + pi.attr("on_parole") = (int)peer_info::on_parole; + pi.attr("seed") = (int)peer_info::seed; +#ifndef TORRENT_DISABLE_ENCRYPTION + pi.attr("rc4_encrypted") = (int)peer_info::rc4_encrypted; + pi.attr("plaintext_encrypted") = (int)peer_info::plaintext_encrypted; +#endif + + // connection_type + pi.attr("standard_bittorrent") = (int)peer_info::standard_bittorrent; + pi.attr("web_seed") = (int)peer_info::web_seed; + + // source + pi.attr("tracker") = (int)peer_info::tracker; + pi.attr("dht") = (int)peer_info::dht; + pi.attr("pex") = (int)peer_info::pex; + pi.attr("lsd") = (int)peer_info::lsd; + pi.attr("resume_data") = (int)peer_info::resume_data; + + // read/write state + pi.attr("bw_idle") = (int)peer_info::bw_idle; + pi.attr("bw_torrent") = (int)peer_info::bw_torrent; + pi.attr("bw_global") = (int)peer_info::bw_global; + pi.attr("bw_network") = (int)peer_info::bw_network; +} + diff --git a/libtorrent/bindings/python/src/peer_plugin.cpp b/libtorrent/bindings/python/src/peer_plugin.cpp new file mode 100755 index 000000000..eaca35484 --- /dev/null +++ b/libtorrent/bindings/python/src/peer_plugin.cpp @@ -0,0 +1,356 @@ +// Copyright Daniel Wallin 2007. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::python; +using namespace libtorrent; + +namespace +{ + struct peer_plugin_wrap : peer_plugin, wrapper + { + void add_handshake(entry& e) + { + if (override f = this->get_override("add_handshake")) + e = call(f.ptr(), e); + else + peer_plugin::add_handshake(e); + } + + void default_add_handshake(entry& e) + { + this->peer_plugin::add_handshake(e); + } + + bool on_handshake(char const* reserved_bits) + { + if (override f = this->get_override("on_handshake")) + return f(); + else + return peer_plugin::on_handshake(reserved_bits); + } + + bool default_on_handshake(char const* reserved_bits) + { + return this->peer_plugin::on_handshake(reserved_bits); + } + + bool on_extension_handshake(lazy_entry const& e) + { + if (override f = this->get_override("on_extension_handshake")) + return f(e); + else + return peer_plugin::on_extension_handshake(e); + } + + bool default_on_extension_handshake(lazy_entry const& e) + { + return this->peer_plugin::on_extension_handshake(e); + } + + bool on_choke() + { + if (override f = this->get_override("on_choke")) + return f(); + else + return peer_plugin::on_choke(); + } + + bool default_on_choke() + { + return this->peer_plugin::on_choke(); + } + + bool on_unchoke() + { + if (override f = this->get_override("on_unchoke")) + return f(); + else + return peer_plugin::on_unchoke(); + } + + bool default_on_unchoke() + { + return this->peer_plugin::on_unchoke(); + } + + bool on_interested() + { + if (override f = this->get_override("on_interested")) + return f(); + else + return peer_plugin::on_interested(); + } + + bool default_on_interested() + { + return this->peer_plugin::on_interested(); + } + + bool on_not_interested() + { + if (override f = this->get_override("on_not_interested")) + return f(); + else + return peer_plugin::on_not_interested(); + } + + bool default_on_not_interested() + { + return this->peer_plugin::on_not_interested(); + } + + bool on_have(int index) + { + if (override f = this->get_override("on_have")) + return f(index); + else + return peer_plugin::on_have(index); + } + + bool default_on_have(int index) + { + return this->peer_plugin::on_have(index); + } + + bool on_bitfield(list _bf) + { + //Convert list to a bitfield + bitfield bf(len(_bf)); + for (int i = 0; i < len(_bf); ++i) + { + if (_bf[i]) + bf.set_bit(i); + else + bf.clear_bit(i); + } + if (override f = this->get_override("on_bitfield")) + return f(bf); + else + return peer_plugin::on_bitfield(bf); + } + + bool default_on_bitfield(const bitfield &bf) + { + return this->peer_plugin::on_bitfield(bf); + } + + bool on_request(peer_request const& req) + { + if (override f = this->get_override("on_request")) + return f(req); + else + return peer_plugin::on_request(req); + } + + bool default_on_request(peer_request const& req) + { + return this->peer_plugin::on_request(req); + } + + bool on_piece(peer_request const& piece, disk_buffer_holder& data) + { + if (override f = this->get_override("on_piece")) + return f(piece, data); + else + return peer_plugin::on_piece(piece, data); + } + + bool default_on_piece(peer_request const& piece, disk_buffer_holder& data) + { + return this->peer_plugin::on_piece(piece, data); + } + + bool on_cancel(peer_request const& req) + { + if (override f = this->get_override("on_cancel")) + return f(req); + else + return peer_plugin::on_cancel(req); + } + + bool default_on_cancel(peer_request const& req) + { + return this->peer_plugin::on_cancel(req); + } + + bool on_extended(int length, int msg, buffer::const_interval body) + { + if (override f = this->get_override("on_extended")) + return f(length, msg, body); + else + return peer_plugin::on_extended(length, msg, body); + } + + bool default_on_extended(int length, int msg, buffer::const_interval body) + { + return this->peer_plugin::on_extended(length, msg, body); + } + + bool on_unknown_message(int length, int msg, buffer::const_interval body) + { + if (override f = this->get_override("on_unknown_message")) + return f(length, msg, body); + else + return peer_plugin::on_unknown_message(length, msg, body); + } + + bool default_on_unknown_message(int length, int msg, buffer::const_interval body) + { + return this->peer_plugin::on_unknown_message(length, msg, body); + } + + void on_piece_pass(int index) + { + if (override f = this->get_override("on_piece_pass")) + f(index); + else + peer_plugin::on_piece_pass(index); + } + + void default_on_piece_pass(int index) + { + this->peer_plugin::on_piece_pass(index); + } + + void on_piece_failed(int index) + { + if (override f = this->get_override("on_piece_failed")) + f(index); + else + peer_plugin::on_piece_failed(index); + } + + void default_on_piece_failed(int index) + { + this->peer_plugin::on_piece_failed(index); + } + + void tick() + { + if (override f = this->get_override("tick")) + f(); + else + peer_plugin::tick(); + } + + void default_tick() + { + this->peer_plugin::tick(); + } + + bool write_request(peer_request const& req) + { + if (override f = this->get_override("write_request")) + return f(req); + else + return peer_plugin::write_request(req); + } + + bool default_write_request(peer_request const& req) + { + return this->peer_plugin::write_request(req); + } + }; + + object get_buffer() + { + static char const data[] = "foobar"; + return object(handle<>(PyBuffer_FromMemory((void*)data, 6))); + } + +} // namespace unnamed + +void bind_peer_plugin() +{ + class_< + peer_plugin_wrap, boost::shared_ptr, boost::noncopyable + >("peer_plugin") + .def( + "add_handshake" + , &peer_plugin::add_handshake, &peer_plugin_wrap::default_add_handshake + ) + .def( + "on_handshake" + , &peer_plugin::on_handshake, &peer_plugin_wrap::default_on_handshake + ) + .def( + "on_extension_handshake" + , &peer_plugin::on_extension_handshake + , &peer_plugin_wrap::default_on_extension_handshake + ) + .def( + "on_choke" + , &peer_plugin::on_choke, &peer_plugin_wrap::default_on_choke + ) + .def( + "on_unchoke" + , &peer_plugin::on_unchoke, &peer_plugin_wrap::default_on_unchoke + ) + .def( + "on_interested" + , &peer_plugin::on_interested, &peer_plugin_wrap::default_on_interested + ) + .def( + "on_not_interested" + , &peer_plugin::on_not_interested, &peer_plugin_wrap::default_on_not_interested + ) + .def( + "on_have" + , &peer_plugin::on_have, &peer_plugin_wrap::default_on_have + ) + .def( + "on_bitfield" + , &peer_plugin::on_bitfield, &peer_plugin_wrap::default_on_bitfield + ) + .def( + "on_request" + , &peer_plugin::on_request, &peer_plugin_wrap::default_on_request + ) + .def( + "on_piece" + , &peer_plugin::on_piece, &peer_plugin_wrap::default_on_piece + ) + .def( + "on_cancel" + , &peer_plugin::on_cancel, &peer_plugin_wrap::default_on_cancel + ) + .def( + "on_piece_pass" + , &peer_plugin::on_piece_pass, &peer_plugin_wrap::default_on_piece_pass + ) + .def( + "on_piece_failed" + , &peer_plugin::on_piece_failed, &peer_plugin_wrap::default_on_piece_failed + ) + .def( + "tick" + , &peer_plugin::tick, &peer_plugin_wrap::default_tick + ) + .def( + "write_request" + , &peer_plugin::write_request, &peer_plugin_wrap::default_write_request + ) + // These seem to make VC7.1 freeze. Needs special handling. + + /*.def( + "on_extended" + , &peer_plugin::on_extended, &peer_plugin_wrap::default_on_extended + ) + .def( + "on_unknown_message" + , &peer_plugin::on_unknown_message, &peer_plugin_wrap::default_on_unknown_message + )*/ + ; + + def("get_buffer", &get_buffer); +} + diff --git a/libtorrent/bindings/python/src/session.cpp b/libtorrent/bindings/python/src/session.cpp new file mode 100755 index 000000000..4c9e65e42 --- /dev/null +++ b/libtorrent/bindings/python/src/session.cpp @@ -0,0 +1,349 @@ +// Copyright Daniel Wallin, Arvid Norberg 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include "gil.hpp" + +using namespace boost::python; +using namespace libtorrent; + +extern char const* session_status_doc; +extern char const* session_status_has_incoming_connections_doc; +extern char const* session_status_upload_rate_doc; +extern char const* session_status_download_rate_doc; +extern char const* session_status_payload_upload_rate_doc; +extern char const* session_status_payload_download_rate_doc; +extern char const* session_status_total_download_doc; +extern char const* session_status_total_upload_doc; +extern char const* session_status_total_payload_download_doc; +extern char const* session_status_total_payload_upload_doc; +extern char const* session_status_num_peers_doc; +extern char const* session_status_dht_nodes_doc; +extern char const* session_status_cache_nodes_doc; +extern char const* session_status_dht_torrents_doc; + +extern char const* session_doc; +extern char const* session_init_doc; +extern char const* session_listen_on_doc; +extern char const* session_is_listening_doc; +extern char const* session_listen_port_doc; +extern char const* session_status_m_doc; +extern char const* session_start_dht_doc; +extern char const* session_stop_dht_doc; +extern char const* session_dht_state_doc; +extern char const* session_add_dht_router_doc; +extern char const* session_add_torrent_doc; +extern char const* session_remove_torrent_doc; +extern char const* session_set_download_rate_limit_doc; +extern char const* session_download_rate_limit_doc; +extern char const* session_set_upload_rate_limit_doc; +extern char const* session_upload_rate_limit_doc; +extern char const* session_set_max_uploads_doc; +extern char const* session_set_max_connections_doc; +extern char const* session_set_max_half_open_connections_doc; +extern char const* session_num_connections_doc; +extern char const* session_set_settings_doc; +extern char const* session_set_pe_settings_doc; +extern char const* session_get_pe_settings_doc; +extern char const* session_set_severity_level_doc; +extern char const* session_pop_alert_doc; +extern char const* session_start_upnp_doc; +extern char const* session_start_lsd_doc; +extern char const* session_stop_lsd_doc; +extern char const* session_stop_upnp_doc; +extern char const* session_start_natpmp_doc; +extern char const* session_stop_natpmp_doc; +extern char const* session_set_ip_filter_doc; + +namespace +{ + + bool listen_on(session& s, int min_, int max_, char const* interface) + { + allow_threading_guard guard; + return s.listen_on(std::make_pair(min_, max_), interface); + } + +#ifndef TORRENT_DISABLE_DHT + void add_dht_router(session& s, std::string router_, int port_) + { + allow_threading_guard guard; + return s.add_dht_router(std::make_pair(router_, port_)); + } +#endif + + struct invoke_extension_factory + { + invoke_extension_factory(object const& callback) + : cb(callback) + {} + + boost::shared_ptr operator()(torrent* t, void*) + { + lock_gil lock; + return extract >(cb(ptr(t)))(); + } + + object cb; + }; + + void add_extension(session& s, object const& e) + { + allow_threading_guard guard; + s.add_extension(invoke_extension_factory(e)); + } + + torrent_handle add_torrent(session& s, dict params) + { + add_torrent_params p; + + if (params.has_key("ti")) + p.ti = new torrent_info(extract(params["ti"])); + + std::string url; + if (params.has_key("tracker_url")) + { + url = extract(params["tracker_url"]); + p.tracker_url = url.c_str(); + } + if (params.has_key("info_hash")) + p.info_hash = extract(params["info_hash"]); + std::string name; + if (params.has_key("name")) + { + name = extract(params["name"]); + p.name = name.c_str(); + } + p.save_path = fs::path(extract(params["save_path"])); + + std::vector resume_buf; + if (params.has_key("resume_data")) + { + std::string resume = extract(params["resume_data"]); + resume_buf.resize(resume.size()); + std::memcpy(&resume_buf[0], &resume[0], resume.size()); + p.resume_data = &resume_buf; + } + p.storage_mode = extract(params["storage_mode"]); + p.paused = params["paused"]; + p.auto_managed = params["auto_managed"]; + p.duplicate_is_error = params["duplicate_is_error"]; + + return s.add_torrent(p); + } + + void start_natpmp(session& s) + { + allow_threading_guard guard; + s.start_natpmp(); + return; + } + + void start_upnp(session& s) + { + allow_threading_guard guard; + s.start_upnp(); + return; + } + + list get_torrents(session& s) + { + list ret; + std::vector torrents = s.get_torrents(); + + for (std::vector::iterator i = torrents.begin(); i != torrents.end(); ++i) + { + ret.append(*i); + } + return ret; + } + +#ifndef TORRENT_DISABLE_GEO_IP + bool load_asnum_db(session& s, std::string file) + { + allow_threading_guard guard; + return s.load_asnum_db(file.c_str()); + } + + bool load_country_db(session& s, std::string file) + { + allow_threading_guard guard; + return s.load_country_db(file.c_str()); + } +#endif +} // namespace unnamed + +void bind_session() +{ + class_("session_status", session_status_doc) + .def_readonly( + "has_incoming_connections", &session_status::has_incoming_connections + , session_status_has_incoming_connections_doc + ) + .def_readonly( + "upload_rate", &session_status::upload_rate + , session_status_upload_rate_doc + ) + .def_readonly( + "download_rate", &session_status::download_rate + , session_status_download_rate_doc + ) + .def_readonly( + "payload_upload_rate", &session_status::payload_upload_rate + , session_status_payload_upload_rate_doc + ) + .def_readonly( + "payload_download_rate", &session_status::payload_download_rate + , session_status_payload_download_rate_doc + ) + .def_readonly( + "total_download", &session_status::total_download + , session_status_total_download_doc + ) + .def_readonly( + "total_upload", &session_status::total_upload + , session_status_total_upload_doc + ) + .def_readonly( + "total_payload_download", &session_status::total_payload_download + , session_status_total_payload_download_doc + ) + .def_readonly( + "total_payload_upload", &session_status::total_payload_upload + , session_status_total_payload_upload_doc + ) + .def_readonly( + "num_peers", &session_status::num_peers + , session_status_num_peers_doc + ) +#ifndef TORRENT_DISABLE_DHT + .def_readonly( + "dht_nodes", &session_status::dht_nodes + , session_status_dht_nodes_doc + ) + .def_readonly( + "dht_cache_nodes", &session_status::dht_node_cache + , session_status_cache_nodes_doc + ) + .def_readonly( + "dht_torrents", &session_status::dht_torrents + , session_status_dht_torrents_doc + ) +#endif + ; + + enum_("storage_mode_t") + .value("storage_mode_allocate", storage_mode_allocate) + .value("storage_mode_sparse", storage_mode_sparse) + .value("storage_mode_compact", storage_mode_compact) + ; + + enum_("options_t") + .value("none", session::none) + .value("delete_files", session::delete_files) + ; + + class_("session", session_doc, no_init) + .def( + init(arg("fingerprint")=fingerprint("LT",0,1,0,0), session_init_doc) + ) + .def( + "listen_on", &listen_on + , (arg("min"), "max", arg("interface") = (char const*)0) + , session_listen_on_doc + ) + .def("is_listening", allow_threads(&session::is_listening), session_is_listening_doc) + .def("listen_port", allow_threads(&session::listen_port), session_listen_port_doc) + .def("status", allow_threads(&session::status), session_status_m_doc) +#ifndef TORRENT_DISABLE_DHT + .def( + "add_dht_router", &add_dht_router + , (arg("router"), "port") + , session_add_dht_router_doc + ) + .def("start_dht", allow_threads(&session::start_dht), session_start_dht_doc) + .def("stop_dht", allow_threads(&session::stop_dht), session_stop_dht_doc) + .def("dht_state", allow_threads(&session::dht_state), session_dht_state_doc) + .def("set_dht_proxy", allow_threads(&session::set_dht_proxy)) +#endif + .def("add_torrent", &add_torrent, session_add_torrent_doc) + .def("remove_torrent", allow_threads(&session::remove_torrent), arg("option") = session::none + , session_remove_torrent_doc) + .def( + "set_download_rate_limit", allow_threads(&session::set_download_rate_limit) + , session_set_download_rate_limit_doc + ) + .def( + "download_rate_limit", allow_threads(&session::download_rate_limit) + , session_download_rate_limit_doc + ) + + .def( + "set_upload_rate_limit", allow_threads(&session::set_upload_rate_limit) + , session_set_upload_rate_limit_doc + ) + .def( + "upload_rate_limit", allow_threads(&session::upload_rate_limit) + , session_upload_rate_limit_doc + ) + + .def( + "set_max_uploads", allow_threads(&session::set_max_uploads) + , session_set_max_uploads_doc + ) + .def( + "set_max_connections", allow_threads(&session::set_max_connections) + , session_set_max_connections_doc + ) + .def( + "set_max_half_open_connections", allow_threads(&session::set_max_half_open_connections) + , session_set_max_half_open_connections_doc + ) + .def( + "num_connections", allow_threads(&session::num_connections) + , session_num_connections_doc + ) + .def("set_settings", allow_threads(&session::set_settings), session_set_settings_doc) +#ifndef TORRENT_DISABLE_ENCRYPTION + .def("set_pe_settings", allow_threads(&session::set_pe_settings), session_set_pe_settings_doc) + .def("get_pe_settings", allow_threads(&session::get_pe_settings), return_value_policy()) +#endif +#ifndef TORRENT_DISABLE_GEO_IP + .def("load_asnum_db", &load_asnum_db) + .def("load_country_db", &load_country_db) +#endif + .def("load_state", allow_threads(&session::load_state)) + .def("state", allow_threads(&session::state)) + .def( + "set_severity_level", allow_threads(&session::set_severity_level) + , session_set_severity_level_doc + ) + .def("set_alert_mask", allow_threads(&session::set_alert_mask)) + .def("pop_alert", allow_threads(&session::pop_alert), session_pop_alert_doc) + .def("add_extension", &add_extension) + .def("set_peer_proxy", allow_threads(&session::set_peer_proxy)) + .def("set_tracker_proxy", allow_threads(&session::set_tracker_proxy)) + .def("set_web_seed_proxy", allow_threads(&session::set_web_seed_proxy)) + .def("start_upnp", &start_upnp, session_start_upnp_doc) + .def("stop_upnp", allow_threads(&session::stop_upnp), session_stop_upnp_doc) + .def("start_lsd", allow_threads(&session::start_lsd), session_start_lsd_doc) + .def("stop_lsd", allow_threads(&session::stop_lsd), session_stop_lsd_doc) + .def("start_natpmp", &start_natpmp, session_start_natpmp_doc) + .def("stop_natpmp", allow_threads(&session::stop_natpmp), session_stop_natpmp_doc) + .def("set_ip_filter", allow_threads(&session::set_ip_filter), session_set_ip_filter_doc) + .def("find_torrent", allow_threads(&session::find_torrent)) + .def("get_torrents", &get_torrents) + .def("pause", allow_threads(&session::pause)) + .def("resume", allow_threads(&session::resume)) + .def("is_paused", allow_threads(&session::is_paused)) + ; + + register_ptr_to_python >(); +} + + diff --git a/libtorrent/bindings/python/src/session_settings.cpp b/libtorrent/bindings/python/src/session_settings.cpp new file mode 100755 index 000000000..814c1ad58 --- /dev/null +++ b/libtorrent/bindings/python/src/session_settings.cpp @@ -0,0 +1,90 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::python; +using namespace libtorrent; + +void bind_session_settings() +{ + class_("session_settings") + .def_readwrite("user_agent", &session_settings::user_agent) + .def_readwrite("tracker_completion_timeout", &session_settings::tracker_completion_timeout) + .def_readwrite("tracker_receive_timeout", &session_settings::tracker_receive_timeout) + .def_readwrite("tracker_maximum_response_length", &session_settings::tracker_maximum_response_length) + .def_readwrite("piece_timeout", &session_settings::piece_timeout) + .def_readwrite("request_queue_time", &session_settings::request_queue_time) + .def_readwrite("max_allowed_in_request_queue", &session_settings::max_allowed_in_request_queue) + .def_readwrite("max_out_request_queue", &session_settings::max_out_request_queue) + .def_readwrite("whole_pieces_threshold", &session_settings::whole_pieces_threshold) + .def_readwrite("peer_timeout", &session_settings::peer_timeout) + .def_readwrite("urlseed_timeout", &session_settings::urlseed_timeout) + .def_readwrite("urlseed_pipeline_size", &session_settings::urlseed_pipeline_size) + .def_readwrite("file_pool_size", &session_settings::file_pool_size) + .def_readwrite("allow_multiple_connections_per_ip", &session_settings::allow_multiple_connections_per_ip) + .def_readwrite("max_failcount", &session_settings::max_failcount) + .def_readwrite("min_reconnect_time", &session_settings::min_reconnect_time) + .def_readwrite("peer_connect_timeout", &session_settings::peer_connect_timeout) + .def_readwrite("ignore_limits_on_local_network", &session_settings::ignore_limits_on_local_network) + .def_readwrite("connection_speed", &session_settings::connection_speed) + .def_readwrite("send_redundant_have", &session_settings::send_redundant_have) + .def_readwrite("lazy_bitfields", &session_settings::lazy_bitfields) + .def_readwrite("inactivity_timeout", &session_settings::inactivity_timeout) + .def_readwrite("unchoke_interval", &session_settings::unchoke_interval) + .def_readwrite("active_downloads", &session_settings::active_downloads) + .def_readwrite("active_seeds", &session_settings::active_seeds) + .def_readwrite("active_limit", &session_settings::active_limit) + .def_readwrite("dont_count_slow_torrents", &session_settings::dont_count_slow_torrents) + .def_readwrite("auto_manage_interval", &session_settings::auto_manage_interval) + .def_readwrite("share_ratio_limit", &session_settings::share_ratio_limit) + .def_readwrite("seed_time_ratio_limit", &session_settings::seed_time_ratio_limit) + .def_readwrite("seed_time_limit", &session_settings::seed_time_limit) + .def_readwrite("auto_scraped_interval", &session_settings::auto_scrape_interval) +#ifndef TORRENT_DISABLE_DHT + .def_readwrite("use_dht_as_fallback", &session_settings::use_dht_as_fallback) +#endif + ; + + enum_("proxy_type") + .value("none", proxy_settings::none) + .value("socks4", proxy_settings::socks4) + .value("socks5", proxy_settings::socks5) + .value("socks5_pw", proxy_settings::socks5_pw) + .value("http", proxy_settings::http) + .value("http_pw", proxy_settings::http_pw) + ; + class_("proxy_settings") + .def_readwrite("hostname", &proxy_settings::hostname) + .def_readwrite("port", &proxy_settings::port) + .def_readwrite("password", &proxy_settings::password) + .def_readwrite("username", &proxy_settings::username) + .def_readwrite("type", &proxy_settings::type) + ; + +#ifndef TORRENT_DISABLE_ENCRYPTION + enum_("enc_policy") + .value("forced", pe_settings::forced) + .value("enabled", pe_settings::enabled) + .value("disabled", pe_settings::disabled) + ; + + enum_("enc_level") + .value("rc4", pe_settings::rc4) + .value("plaintext", pe_settings::plaintext) + .value("both", pe_settings::both) + ; + + class_("pe_settings") + .def_readwrite("out_enc_policy", &pe_settings::out_enc_policy) + .def_readwrite("in_enc_policy", &pe_settings::in_enc_policy) + .def_readwrite("allowed_enc_level", &pe_settings::allowed_enc_level) + .def_readwrite("prefer_rc4", &pe_settings::prefer_rc4) + ; +#endif + +} + + diff --git a/libtorrent/bindings/python/src/torrent.cpp b/libtorrent/bindings/python/src/torrent.cpp new file mode 100755 index 000000000..7b2ba76b4 --- /dev/null +++ b/libtorrent/bindings/python/src/torrent.cpp @@ -0,0 +1,15 @@ +// Copyright Daniel Wallin 2007. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::python; +using namespace libtorrent; + +void bind_torrent() +{ + class_("torrent", no_init); +} + diff --git a/libtorrent/bindings/python/src/torrent_handle.cpp b/libtorrent/bindings/python/src/torrent_handle.cpp new file mode 100755 index 000000000..9980e940f --- /dev/null +++ b/libtorrent/bindings/python/src/torrent_handle.cpp @@ -0,0 +1,318 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include "gil.hpp" + +using namespace boost::python; +using namespace libtorrent; + +namespace +{ + + list url_seeds(torrent_handle& handle) + { + list ret; + std::set urls; + { + allow_threading_guard guard; + urls = handle.url_seeds(); + } + + for (std::set::iterator i(urls.begin()) + , end(urls.end()); i != end; ++i) + ret.append(*i); + return ret; + } + + list piece_availability(torrent_handle& handle) + { + list ret; + std::vector avail; + { + allow_threading_guard guard; + handle.piece_availability(avail); + } + + for (std::vector::iterator i(avail.begin()) + , end(avail.end()); i != end; ++i) + ret.append(*i); + return ret; + } + + list piece_priorities(torrent_handle& handle) + { + list ret; + std::vector prio; + { + allow_threading_guard guard; + prio = handle.piece_priorities(); + } + + for (std::vector::iterator i(prio.begin()) + , end(prio.end()); i != end; ++i) + ret.append(*i); + return ret; + } + + std::vector::const_iterator begin_trackers(torrent_handle& i) + { + allow_threading_guard guard; + return i.trackers().begin(); + } + + std::vector::const_iterator end_trackers(torrent_handle& i) + { + allow_threading_guard guard; + return i.trackers().end(); + } + +} // namespace unnamed + +list file_progress(torrent_handle& handle) +{ + std::vector p; + + { + allow_threading_guard guard; + p.reserve(handle.get_torrent_info().num_files()); + handle.file_progress(p); + } + + list result; + + for (std::vector::iterator i(p.begin()), e(p.end()); i != e; ++i) + result.append(*i); + + return result; +} + +list get_peer_info(torrent_handle const& handle) +{ + std::vector pi; + + { + allow_threading_guard guard; + handle.get_peer_info(pi); + } + + list result; + + for (std::vector::iterator i = pi.begin(); i != pi.end(); ++i) + result.append(*i); + + return result; +} + +void prioritize_pieces(torrent_handle& info, object o) +{ + std::vector result; + try + { + object iter_obj = object( handle<>( PyObject_GetIter( o.ptr() ) )); + while( 1 ) + { + object obj = extract( iter_obj.attr( "next" )() ); + result.push_back(extract( obj )); + } + } + catch( error_already_set ) + { + PyErr_Clear(); + info.prioritize_pieces(result); + return; + } +} + +void prioritize_files(torrent_handle& info, object o) +{ + std::vector result; + try + { + object iter_obj = object( handle<>( PyObject_GetIter( o.ptr() ) )); + while( 1 ) + { + object obj = extract( iter_obj.attr( "next" )() ); + result.push_back(extract( obj )); + } + } + catch( error_already_set ) + { + PyErr_Clear(); + info.prioritize_files(result); + return; + } +} + + +void replace_trackers(torrent_handle& info, object trackers) +{ + object iter(trackers.attr("__iter__")()); + + std::vector result; + + for (;;) + { + handle<> entry(allow_null(PyIter_Next(iter.ptr()))); + + if (entry == handle<>()) + break; + + result.push_back(extract(object(entry))); + } + + allow_threading_guard guard; + info.replace_trackers(result); +} + +list get_download_queue(torrent_handle& handle) +{ + list ret; + + std::vector downloading; + + { + allow_threading_guard guard; + handle.get_download_queue(downloading); + } + + for (std::vector::iterator i = downloading.begin() + , end(downloading.end()); i != end; ++i) + { + dict partial_piece; + partial_piece["piece_index"] = i->piece_index; + partial_piece["blocks_in_piece"] = i->blocks_in_piece; + list block_list; + for (int k = 0; k < i->blocks_in_piece; ++k) + { + dict block_info; + block_info["state"] = i->blocks[k].state; + block_info["num_peers"] = i->blocks[k].num_peers; + block_info["bytes_progress"] = i->blocks[k].bytes_progress; + block_info["block_size"] = i->blocks[k].block_size; + block_info["peer"] = std::make_pair( + boost::lexical_cast(i->blocks[k].peer.address()), i->blocks[k].peer.port()); + block_list.append(block_info); + } + partial_piece["blocks"] = block_list; + + ret.append(partial_piece); + } + + return ret; +} + +namespace +{ + tcp::endpoint tuple_to_endpoint(tuple const& t) + { + return tcp::endpoint(address::from_string(extract(t[0])), extract(t[1])); + } +} + +void force_reannounce(torrent_handle& th, int s) +{ + th.force_reannounce(boost::posix_time::seconds(s)); +} + +void connect_peer(torrent_handle& th, tuple ip, int source) +{ + th.connect_peer(tuple_to_endpoint(ip), source); +} + +void set_peer_upload_limit(torrent_handle& th, tuple const& ip, int limit) +{ + th.set_peer_upload_limit(tuple_to_endpoint(ip), limit); +} + +void set_peer_download_limit(torrent_handle& th, tuple const& ip, int limit) +{ + th.set_peer_download_limit(tuple_to_endpoint(ip), limit); +} + +void bind_torrent_handle() +{ + void (torrent_handle::*force_reannounce0)() const = &torrent_handle::force_reannounce; + + int (torrent_handle::*piece_priority0)(int) const = &torrent_handle::piece_priority; + void (torrent_handle::*piece_priority1)(int, int) const = &torrent_handle::piece_priority; + +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + bool (torrent_handle::*resolve_countries0)() const = &torrent_handle::resolve_countries; + void (torrent_handle::*resolve_countries1)(bool) = &torrent_handle::resolve_countries; +#endif + + return_value_policy copy; + +#define _ allow_threads + + class_("torrent_handle") + .def("get_peer_info", get_peer_info) + .def("status", _(&torrent_handle::status)) + .def("get_download_queue", get_download_queue) + .def("file_progress", file_progress) + .def("trackers", range(begin_trackers, end_trackers)) + .def("replace_trackers", replace_trackers) + .def("add_url_seed", _(&torrent_handle::add_url_seed)) + .def("remove_url_seed", _(&torrent_handle::remove_url_seed)) + .def("url_seeds", url_seeds) + .def("has_metadata", _(&torrent_handle::has_metadata)) + .def("get_torrent_info", _(&torrent_handle::get_torrent_info), return_internal_reference<>()) + .def("is_valid", _(&torrent_handle::is_valid)) + .def("is_seed", _(&torrent_handle::is_seed)) + .def("is_finished", _(&torrent_handle::is_finished)) + .def("is_paused", _(&torrent_handle::is_paused)) + .def("pause", _(&torrent_handle::pause)) + .def("resume", _(&torrent_handle::resume)) + + .def("is_auto_managed", _(&torrent_handle::is_auto_managed)) + .def("auto_managed", _(&torrent_handle::auto_managed)) + .def("queue_position", _(&torrent_handle::queue_position)) + .def("queue_position_up", _(&torrent_handle::queue_position_up)) + .def("queue_position_down", _(&torrent_handle::queue_position_down)) + .def("queue_position_top", _(&torrent_handle::queue_position_top)) + .def("queue_position_bottom", _(&torrent_handle::queue_position_bottom)) + +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + .def("resolve_countries", _(resolve_countries0)) + .def("resolve_countries", _(resolve_countries1)) +#endif + // deprecated + .def("filter_piece", _(&torrent_handle::filter_piece)) + .def("is_piece_filtered", _(&torrent_handle::is_piece_filtered)) + + .def("piece_availability", piece_availability) + .def("piece_priority", _(piece_priority0)) + .def("piece_priority", _(piece_priority1)) + .def("prioritize_pieces", prioritize_pieces) + .def("piece_prioritize", piece_priorities) + .def("prioritize_files", prioritize_files) + .def("use_interface", &torrent_handle::use_interface) + .def("write_resume_data", _(&torrent_handle::write_resume_data)) + .def("save_resume_data", _(&torrent_handle::save_resume_data)) + .def("force_reannounce", _(force_reannounce0)) + .def("force_reannounce", force_reannounce) + .def("scrape_tracker", _(&torrent_handle::scrape_tracker)) + .def("name", _(&torrent_handle::name)) + .def("set_upload_limit", _(&torrent_handle::set_upload_limit)) + .def("upload_limit", _(&torrent_handle::upload_limit)) + .def("set_download_limit", _(&torrent_handle::set_download_limit)) + .def("download_limit", _(&torrent_handle::download_limit)) + .def("set_sequential_download", _(&torrent_handle::set_sequential_download)) + .def("set_peer_upload_limit", set_peer_upload_limit) + .def("set_peer_download_limit", set_peer_download_limit) + .def("connect_peer", connect_peer) + .def("set_ratio", _(&torrent_handle::set_ratio)) + .def("save_path", _(&torrent_handle::save_path)) + .def("set_max_uploads", _(&torrent_handle::set_max_uploads)) + .def("set_max_connections", _(&torrent_handle::set_max_connections)) + .def("set_tracker_login", _(&torrent_handle::set_tracker_login)) + .def("move_storage", _(&torrent_handle::move_storage)) + .def("info_hash", _(&torrent_handle::info_hash)) + .def("force_recheck", _(&torrent_handle::force_recheck)) + ; +} + diff --git a/libtorrent/bindings/python/src/torrent_info.cpp b/libtorrent/bindings/python/src/torrent_info.cpp new file mode 100755 index 000000000..55e7fd6b9 --- /dev/null +++ b/libtorrent/bindings/python/src/torrent_info.cpp @@ -0,0 +1,123 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "libtorrent/intrusive_ptr_base.hpp" + +using namespace boost::python; +using namespace libtorrent; + +namespace +{ + + std::vector::const_iterator begin_trackers(torrent_info& i) + { + return i.trackers().begin(); + } + + std::vector::const_iterator end_trackers(torrent_info& i) + { + return i.trackers().end(); + } + + void add_node(torrent_info& ti, char const* hostname, int port) + { + ti.add_node(std::make_pair(hostname, port)); + } + + list nodes(torrent_info const& ti) + { + list result; + + typedef std::vector > list_type; + + for (list_type::const_iterator i = ti.nodes().begin(); i != ti.nodes().end(); ++i) + { + result.append(make_tuple(i->first, i->second)); + } + + return result; + } + + file_storage::iterator begin_files(torrent_info& i) + { + return i.begin_files(); + } + + file_storage::iterator end_files(torrent_info& i) + { + return i.end_files(); + } + + //list files(torrent_info const& ti, bool storage) { + list files(torrent_info const& ti, bool storage) { + list result; + + typedef std::vector list_type; + + for (list_type::const_iterator i = ti.begin_files(); i != ti.end_files(); ++i) + result.append(*i); + + return result; + } + + +} // namespace unnamed + +void bind_torrent_info() +{ + return_value_policy copy; + + class_ >("torrent_info", no_init) + .def(init()) + .def(init()) + .def(init()) + .def(init()) + + .def("add_tracker", &torrent_info::add_tracker, (arg("url"), arg("tier")=0)) + .def("add_url_seed", &torrent_info::add_url_seed) + + .def("name", &torrent_info::name, copy) + .def("comment", &torrent_info::comment, copy) + .def("creator", &torrent_info::creator, copy) + .def("total_size", &torrent_info::total_size) + .def("piece_length", &torrent_info::piece_length) + .def("num_pieces", &torrent_info::num_pieces) + .def("info_hash", &torrent_info::info_hash, copy) + + .def("hash_for_piece", &torrent_info::hash_for_piece) + .def("piece_size", &torrent_info::piece_size) + + .def("num_files", &torrent_info::num_files, (arg("storage")=false)) + .def("file_at", &torrent_info::file_at, return_internal_reference<>()) + .def("files", &files, (arg("storage")=false)) + + .def("priv", &torrent_info::priv) + .def("trackers", range(begin_trackers, end_trackers)) + + .def("creation_date", &torrent_info::creation_date) + + .def("add_node", &add_node) + .def("nodes", &nodes) + ; + + class_("file_entry") + .add_property( + "path" + , make_getter( + &file_entry::path, return_value_policy() + ) + ) + .def_readonly("offset", &file_entry::offset) + .def_readonly("size", &file_entry::size) + ; + + class_("announce_entry", init()) + .def_readwrite("url", &announce_entry::url) + .def_readwrite("tier", &announce_entry::tier) + ; +} + + diff --git a/libtorrent/bindings/python/src/torrent_status.cpp b/libtorrent/bindings/python/src/torrent_status.cpp new file mode 100755 index 000000000..186d0f2f5 --- /dev/null +++ b/libtorrent/bindings/python/src/torrent_status.cpp @@ -0,0 +1,91 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +using namespace boost::python; +using namespace libtorrent; + +object pieces(torrent_status const& s) +{ + list result; + + for (bitfield::const_iterator i(s.pieces.begin()), e(s.pieces.end()); i != e; ++i) + result.append(*i); + + return result; +} + +void bind_torrent_status() +{ + scope status = class_("torrent_status") + .def_readonly("state", &torrent_status::state) + .def_readonly("paused", &torrent_status::paused) + .def_readonly("progress", &torrent_status::progress) + .add_property( + "next_announce" + , make_getter( + &torrent_status::next_announce, return_value_policy() + ) + ) + .add_property( + "announce_interval" + , make_getter( + &torrent_status::announce_interval, return_value_policy() + ) + ) + .def_readonly("current_tracker", &torrent_status::current_tracker) + .def_readonly("total_download", &torrent_status::total_download) + .def_readonly("total_upload", &torrent_status::total_upload) + .def_readonly("total_payload_download", &torrent_status::total_payload_download) + .def_readonly("total_payload_upload", &torrent_status::total_payload_upload) + .def_readonly("total_failed_bytes", &torrent_status::total_failed_bytes) + .def_readonly("total_redundant_bytes", &torrent_status::total_redundant_bytes) + .def_readonly("download_rate", &torrent_status::download_rate) + .def_readonly("upload_rate", &torrent_status::upload_rate) + .def_readonly("download_payload_rate", &torrent_status::download_payload_rate) + .def_readonly("upload_payload_rate", &torrent_status::upload_payload_rate) + .def_readonly("num_seeds", &torrent_status::num_seeds) + .def_readonly("num_peers", &torrent_status::num_peers) + .def_readonly("num_complete", &torrent_status::num_complete) + .def_readonly("num_incomplete", &torrent_status::num_incomplete) + .def_readonly("list_seeds", &torrent_status::list_seeds) + .def_readonly("list_peers", &torrent_status::list_peers) + .add_property("pieces", pieces) + .def_readonly("num_pieces", &torrent_status::num_pieces) + .def_readonly("total_done", &torrent_status::total_done) + .def_readonly("total_wanted_done", &torrent_status::total_wanted_done) + .def_readonly("total_wanted", &torrent_status::total_wanted) + .def_readonly("distributed_copies", &torrent_status::distributed_copies) + .def_readonly("block_size", &torrent_status::block_size) + .def_readonly("num_uploads", &torrent_status::num_uploads) + .def_readonly("num_connections", &torrent_status::num_connections) + .def_readonly("uploads_limit", &torrent_status::uploads_limit) + .def_readonly("connections_limit", &torrent_status::connections_limit) + .def_readonly("storage_mode", &torrent_status::storage_mode) + .def_readonly("up_bandwidth_queue", &torrent_status::up_bandwidth_queue) + .def_readonly("down_bandwidth_queue", &torrent_status::down_bandwidth_queue) + .def_readonly("all_time_upload", &torrent_status::all_time_upload) + .def_readonly("all_time_download", &torrent_status::all_time_download) + .def_readonly("active_time", &torrent_status::active_time) + .def_readonly("seeding_time", &torrent_status::seeding_time) + .def_readonly("seed_rank", &torrent_status::seed_rank) + .def_readonly("last_scrape", &torrent_status::last_scrape) + .def_readonly("error", &torrent_status::error) + ; + + enum_("states") + .value("queued_for_checking", torrent_status::queued_for_checking) + .value("checking_files", torrent_status::checking_files) + .value("connecting_to_tracker", torrent_status::connecting_to_tracker) + .value("downloading", torrent_status::downloading) + .value("finished", torrent_status::finished) + .value("seeding", torrent_status::seeding) + .value("allocating", torrent_status::allocating) + .export_values() + ; +} + diff --git a/libtorrent/bindings/python/src/utility.cpp b/libtorrent/bindings/python/src/utility.cpp new file mode 100755 index 000000000..9ae2d2a93 --- /dev/null +++ b/libtorrent/bindings/python/src/utility.cpp @@ -0,0 +1,37 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +using namespace boost::python; +using namespace libtorrent; + +object client_fingerprint_(peer_id const& id) +{ + boost::optional result = client_fingerprint(id); + return result ? object(*result) : object(); +} + +entry bdecode_(std::string const& data) +{ + return bdecode(data.begin(), data.end()); +} + +std::string bencode_(entry const& e) +{ + std::string result; + bencode(std::back_inserter(result), e); + return result; +} + +void bind_utility() +{ + def("identify_client", &libtorrent::identify_client); + def("client_fingerprint", &client_fingerprint_); + def("bdecode", &bdecode_); + def("bencode", &bencode_); +} + diff --git a/libtorrent/bindings/python/src/version.cpp b/libtorrent/bindings/python/src/version.cpp new file mode 100755 index 000000000..aaeafd900 --- /dev/null +++ b/libtorrent/bindings/python/src/version.cpp @@ -0,0 +1,16 @@ +// Copyright Daniel Wallin 2006. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::python; + +void bind_version() +{ + scope().attr("version") = LIBTORRENT_VERSION; + scope().attr("version_major") = LIBTORRENT_VERSION_MAJOR; + scope().attr("version_minor") = LIBTORRENT_VERSION_MINOR; +} + diff --git a/libtorrent/include/libtorrent/asio/COPYING b/libtorrent/include/asio/COPYING similarity index 71% rename from libtorrent/include/libtorrent/asio/COPYING rename to libtorrent/include/asio/COPYING index b68879a1a..61f5a0b12 100644 --- a/libtorrent/include/libtorrent/asio/COPYING +++ b/libtorrent/include/asio/COPYING @@ -1,4 +1,4 @@ -Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com) +Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/libtorrent/include/libtorrent/asio/LICENSE_1_0.txt b/libtorrent/include/asio/LICENSE_1_0.txt similarity index 100% rename from libtorrent/include/libtorrent/asio/LICENSE_1_0.txt rename to libtorrent/include/asio/LICENSE_1_0.txt diff --git a/libtorrent/include/libtorrent/asio/basic_datagram_socket.hpp b/libtorrent/include/asio/basic_datagram_socket.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/basic_datagram_socket.hpp rename to libtorrent/include/asio/basic_datagram_socket.hpp diff --git a/libtorrent/include/libtorrent/asio/basic_deadline_timer.hpp b/libtorrent/include/asio/basic_deadline_timer.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/basic_deadline_timer.hpp rename to libtorrent/include/asio/basic_deadline_timer.hpp diff --git a/libtorrent/include/libtorrent/asio/basic_io_object.hpp b/libtorrent/include/asio/basic_io_object.hpp similarity index 90% rename from libtorrent/include/libtorrent/asio/basic_io_object.hpp rename to libtorrent/include/asio/basic_io_object.hpp index 790498d46..6e369ab4d 100644 --- a/libtorrent/include/libtorrent/asio/basic_io_object.hpp +++ b/libtorrent/include/asio/basic_io_object.hpp @@ -63,6 +63,10 @@ public: protected: /// Construct a basic_io_object. + /** + * Performs: + * @code service.construct(implementation); @endcode + */ explicit basic_io_object(asio::io_service& io_service) : service(asio::use_service(io_service)) { @@ -70,15 +74,19 @@ protected: } /// Protected destructor to prevent deletion through this type. + /** + * Performs: + * @code service.destroy(implementation); @endcode + */ ~basic_io_object() { service.destroy(implementation); } - // The backend service implementation. + /// The service associated with the I/O object. service_type& service; - // The underlying native implementation. + /// The underlying implementation of the I/O object. implementation_type implementation; }; diff --git a/libtorrent/include/asio/basic_raw_socket.hpp b/libtorrent/include/asio/basic_raw_socket.hpp new file mode 100644 index 000000000..5e2f033bd --- /dev/null +++ b/libtorrent/include/asio/basic_raw_socket.hpp @@ -0,0 +1,798 @@ +// +// basic_raw_socket.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_RAW_SOCKET_HPP +#define ASIO_BASIC_RAW_SOCKET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/basic_socket.hpp" +#include "asio/raw_socket_service.hpp" +#include "asio/error.hpp" +#include "asio/detail/throw_error.hpp" + +namespace asio { + +/// Provides raw-oriented socket functionality. +/** + * The basic_raw_socket class template provides asynchronous and blocking + * raw-oriented socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template > +class basic_raw_socket + : public basic_socket +{ +public: + /// The native representation of a socket. + typedef typename RawSocketService::native_type native_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_raw_socket without opening it. + /** + * This constructor creates a raw socket without opening it. The open() + * function must be called before data can be sent or received on the socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + */ + explicit basic_raw_socket(asio::io_service& io_service) + : basic_socket(io_service) + { + } + + /// Construct and open a basic_raw_socket. + /** + * This constructor creates and opens a raw socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws asio::system_error Thrown on failure. + */ + basic_raw_socket(asio::io_service& io_service, + const protocol_type& protocol) + : basic_socket(io_service, protocol) + { + } + + /// Construct a basic_raw_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a raw socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param endpoint An endpoint on the local machine to which the raw + * socket will be bound. + * + * @throws asio::system_error Thrown on failure. + */ + basic_raw_socket(asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_socket(io_service, endpoint) + { + } + + /// Construct a basic_raw_socket on an existing native socket. + /** + * This constructor creates a raw socket object to hold an existing + * native socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws asio::system_error Thrown on failure. + */ + basic_raw_socket(asio::io_service& io_service, + const protocol_type& protocol, const native_type& native_socket) + : basic_socket( + io_service, protocol, native_socket) + { + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @returns The number of bytes sent. + * + * @throws asio::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code socket.send(asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send(const ConstBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->service.send(this->implementation, buffers, 0, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws asio::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + asio::error_code ec; + std::size_t s = this->service.send( + this->implementation, buffers, flags, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + return this->service.send(this->implementation, buffers, flags, ec); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected raw + * socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_send(const ConstBufferSequence& buffers, WriteHandler handler) + { + this->service.async_send(this->implementation, buffers, 0, handler); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected raw + * socket. + */ + template + void async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, WriteHandler handler) + { + this->service.async_send(this->implementation, buffers, flags, handler); + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @returns The number of bytes sent. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * asio::ip::udp::endpoint destination( + * asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.send_to(asio::buffer(data, size), destination); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination) + { + asio::error_code ec; + std::size_t s = this->service.send_to( + this->implementation, buffers, destination, 0, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws asio::system_error Thrown on failure. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags) + { + asio::error_code ec; + std::size_t s = this->service.send_to( + this->implementation, buffers, destination, flags, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + asio::error_code& ec) + { + return this->service.send_to(this->implementation, + buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send raw data to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * asio::ip::udp::endpoint destination( + * asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_send_to( + * asio::buffer(data, size), destination, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, WriteHandler handler) + { + this->service.async_send_to(this->implementation, buffers, destination, 0, + handler); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send raw data to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + */ + template + void async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + WriteHandler handler) + { + this->service.async_send_to(this->implementation, buffers, destination, + flags, handler); + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @returns The number of bytes received. + * + * @throws asio::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.receive(asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive(const MutableBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->service.receive( + this->implementation, buffers, 0, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws asio::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags) + { + asio::error_code ec; + std::size_t s = this->service.receive( + this->implementation, buffers, flags, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + return this->service.receive(this->implementation, buffers, flags, ec); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the raw + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * raw socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_receive(const MutableBufferSequence& buffers, ReadHandler handler) + { + this->service.async_receive(this->implementation, buffers, 0, handler); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the raw + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * raw socket. + */ + template + void async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, ReadHandler handler) + { + this->service.async_receive(this->implementation, buffers, flags, handler); + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @returns The number of bytes received. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * asio::ip::udp::endpoint sender_endpoint; + * socket.receive_from( + * asio::buffer(data, size), sender_endpoint); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint) + { + asio::error_code ec; + std::size_t s = this->service.receive_from( + this->implementation, buffers, sender_endpoint, 0, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws asio::system_error Thrown on failure. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags) + { + asio::error_code ec; + std::size_t s = this->service.receive_from( + this->implementation, buffers, sender_endpoint, flags, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + asio::error_code& ec) + { + return this->service.receive_from(this->implementation, buffers, + sender_endpoint, flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive raw data. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.async_receive_from( + * asio::buffer(data, size), 0, sender_endpoint, handler); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, ReadHandler handler) + { + this->service.async_receive_from(this->implementation, buffers, + sender_endpoint, 0, handler); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive raw data. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + */ + template + void async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + ReadHandler handler) + { + this->service.async_receive_from(this->implementation, buffers, + sender_endpoint, flags, handler); + } +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BASIC_RAW_SOCKET_HPP diff --git a/libtorrent/include/asio/basic_serial_port.hpp b/libtorrent/include/asio/basic_serial_port.hpp new file mode 100644 index 000000000..ffe2b0213 --- /dev/null +++ b/libtorrent/include/asio/basic_serial_port.hpp @@ -0,0 +1,608 @@ +// +// basic_serial_port.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_SERIAL_PORT_HPP +#define ASIO_BASIC_SERIAL_PORT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/basic_io_object.hpp" +#include "asio/error.hpp" +#include "asio/serial_port_base.hpp" +#include "asio/serial_port_service.hpp" +#include "asio/detail/throw_error.hpp" + +#if defined(ASIO_HAS_SERIAL_PORT) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { + +/// Provides serial port functionality. +/** + * The basic_serial_port class template provides functionality that is common + * to all serial ports. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_serial_port + : public basic_io_object, + public serial_port_base +{ +public: + /// The native representation of a serial port. + typedef typename SerialPortService::native_type native_type; + + /// A basic_serial_port is always the lowest layer. + typedef basic_serial_port lowest_layer_type; + + /// Construct a basic_serial_port without opening it. + /** + * This constructor creates a serial port without opening it. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + */ + explicit basic_serial_port(asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Construct and open a basic_serial_port. + /** + * This constructor creates and opens a serial port for the specified device + * name. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param device The platform-specific device name for this serial + * port. + */ + explicit basic_serial_port(asio::io_service& io_service, + const char* device) + : basic_io_object(io_service) + { + asio::error_code ec; + this->service.open(this->implementation, device, ec); + asio::detail::throw_error(ec); + } + + /// Construct and open a basic_serial_port. + /** + * This constructor creates and opens a serial port for the specified device + * name. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param device The platform-specific device name for this serial + * port. + */ + explicit basic_serial_port(asio::io_service& io_service, + const std::string& device) + : basic_io_object(io_service) + { + asio::error_code ec; + this->service.open(this->implementation, device, ec); + asio::detail::throw_error(ec); + } + + /// Construct a basic_serial_port on an existing native serial port. + /** + * This constructor creates a serial port object to hold an existing native + * serial port. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param native_serial_port A native serial port. + * + * @throws asio::system_error Thrown on failure. + */ + basic_serial_port(asio::io_service& io_service, + const native_type& native_serial_port) + : basic_io_object(io_service) + { + asio::error_code ec; + this->service.assign(this->implementation, native_serial_port, ec); + asio::detail::throw_error(ec); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_serial_port cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Open the serial port using the specified device name. + /** + * This function opens the serial port for the specified device name. + * + * @param device The platform-specific device name. + * + * @throws asio::system_error Thrown on failure. + */ + void open(const std::string& device) + { + asio::error_code ec; + this->service.open(this->implementation, device, ec); + asio::detail::throw_error(ec); + } + + /// Open the serial port using the specified device name. + /** + * This function opens the serial port using the given platform-specific + * device name. + * + * @param device The platform-specific device name. + * + * @param ec Set the indicate what error occurred, if any. + */ + asio::error_code open(const std::string& device, + asio::error_code& ec) + { + return this->service.open(this->implementation, device, ec); + } + + /// Assign an existing native serial port to the serial port. + /* + * This function opens the serial port to hold an existing native serial port. + * + * @param native_serial_port A native serial port. + * + * @throws asio::system_error Thrown on failure. + */ + void assign(const native_type& native_serial_port) + { + asio::error_code ec; + this->service.assign(this->implementation, native_serial_port, ec); + asio::detail::throw_error(ec); + } + + /// Assign an existing native serial port to the serial port. + /* + * This function opens the serial port to hold an existing native serial port. + * + * @param native_serial_port A native serial port. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code assign(const native_type& native_serial_port, + asio::error_code& ec) + { + return this->service.assign(this->implementation, native_serial_port, ec); + } + + /// Determine whether the serial port is open. + bool is_open() const + { + return this->service.is_open(this->implementation); + } + + /// Close the serial port. + /** + * This function is used to close the serial port. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + */ + void close() + { + asio::error_code ec; + this->service.close(this->implementation, ec); + asio::detail::throw_error(ec); + } + + /// Close the serial port. + /** + * This function is used to close the serial port. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code close(asio::error_code& ec) + { + return this->service.close(this->implementation, ec); + } + + /// Get the native serial port representation. + /** + * This function may be used to obtain the underlying representation of the + * serial port. This is intended to allow access to native serial port + * functionality that is not otherwise provided. + */ + native_type native() + { + return this->service.native(this->implementation); + } + + /// Cancel all asynchronous operations associated with the serial port. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + */ + void cancel() + { + asio::error_code ec; + this->service.cancel(this->implementation, ec); + asio::detail::throw_error(ec); + } + + /// Cancel all asynchronous operations associated with the serial port. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code cancel(asio::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Send a break sequence to the serial port. + /** + * This function causes a break sequence of platform-specific duration to be + * sent out the serial port. + * + * @throws asio::system_error Thrown on failure. + */ + void send_break() + { + asio::error_code ec; + this->service.send_break(this->implementation, ec); + asio::detail::throw_error(ec); + } + + /// Send a break sequence to the serial port. + /** + * This function causes a break sequence of platform-specific duration to be + * sent out the serial port. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code send_break(asio::error_code& ec) + { + return this->service.send_break(this->implementation, ec); + } + + /// Set an option on the serial port. + /** + * This function is used to set an option on the serial port. + * + * @param option The option value to be set on the serial port. + * + * @throws asio::system_error Thrown on failure. + * + * @sa SettableSerialPortOption @n + * asio::serial_port_base::baud_rate @n + * asio::serial_port_base::flow_control @n + * asio::serial_port_base::parity @n + * asio::serial_port_base::stop_bits @n + * asio::serial_port_base::character_size + */ + template + void set_option(const SettableSerialPortOption& option) + { + asio::error_code ec; + this->service.set_option(this->implementation, option, ec); + asio::detail::throw_error(ec); + } + + /// Set an option on the serial port. + /** + * This function is used to set an option on the serial port. + * + * @param option The option value to be set on the serial port. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSerialPortOption @n + * asio::serial_port_base::baud_rate @n + * asio::serial_port_base::flow_control @n + * asio::serial_port_base::parity @n + * asio::serial_port_base::stop_bits @n + * asio::serial_port_base::character_size + */ + template + asio::error_code set_option(const SettableSerialPortOption& option, + asio::error_code& ec) + { + return this->service.set_option(this->implementation, option, ec); + } + + /// Get an option from the serial port. + /** + * This function is used to get the current value of an option on the serial + * port. + * + * @param option The option value to be obtained from the serial port. + * + * @throws asio::system_error Thrown on failure. + * + * @sa GettableSerialPortOption @n + * asio::serial_port_base::baud_rate @n + * asio::serial_port_base::flow_control @n + * asio::serial_port_base::parity @n + * asio::serial_port_base::stop_bits @n + * asio::serial_port_base::character_size + */ + template + void get_option(GettableSerialPortOption& option) + { + asio::error_code ec; + this->service.get_option(this->implementation, option, ec); + asio::detail::throw_error(ec); + } + + /// Get an option from the serial port. + /** + * This function is used to get the current value of an option on the serial + * port. + * + * @param option The option value to be obtained from the serial port. + * + * @param ec Set to indicate what error occured, if any. + * + * @sa GettableSerialPortOption @n + * asio::serial_port_base::baud_rate @n + * asio::serial_port_base::flow_control @n + * asio::serial_port_base::parity @n + * asio::serial_port_base::stop_bits @n + * asio::serial_port_base::character_size + */ + template + asio::error_code get_option(GettableSerialPortOption& option, + asio::error_code& ec) + { + return this->service.get_option(this->implementation, option, ec); + } + + /// Write some data to the serial port. + /** + * This function is used to write data to the serial port. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the serial port. + * + * @returns The number of bytes written. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.write_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->service.write_some(this->implementation, buffers, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the serial port. + /** + * This function is used to write data to the serial port. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the serial port. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + asio::error_code& ec) + { + return this->service.write_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the serial port. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the serial port. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.async_write_some(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + this->service.async_write_some(this->implementation, buffers, handler); + } + + /// Read some data from the serial port. + /** + * This function is used to read data from the serial port. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.read_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->service.read_some(this->implementation, buffers, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the serial port. + /** + * This function is used to read data from the serial port. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + asio::error_code& ec) + { + return this->service.read_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the serial port. + * The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.async_read_some(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + this->service.async_read_some(this->implementation, buffers, handler); + } +}; + +} // namespace asio + +#endif // defined(ASIO_HAS_SERIAL_PORT) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BASIC_SERIAL_PORT_HPP diff --git a/libtorrent/include/libtorrent/asio/basic_socket.hpp b/libtorrent/include/asio/basic_socket.hpp similarity index 99% rename from libtorrent/include/libtorrent/asio/basic_socket.hpp rename to libtorrent/include/asio/basic_socket.hpp index 5335614fa..f494c1725 100644 --- a/libtorrent/include/libtorrent/asio/basic_socket.hpp +++ b/libtorrent/include/asio/basic_socket.hpp @@ -514,7 +514,7 @@ public: * * The socket is automatically opened if it is not already open. If the * connect fails, and the socket was automatically opened, the socket is - * returned to the closed state. + * not returned to the closed state. * * @param peer_endpoint The remote endpoint to which the socket will be * connected. @@ -549,7 +549,7 @@ public: * * The socket is automatically opened if it is not already open. If the * connect fails, and the socket was automatically opened, the socket is - * returned to the closed state. + * not returned to the closed state. * * @param peer_endpoint The remote endpoint to which the socket will be * connected. @@ -591,7 +591,7 @@ public: * * The socket is automatically opened if it is not already open. If the * connect fails, and the socket was automatically opened, the socket is - * returned to the closed state. + * not returned to the closed state. * * @param peer_endpoint The remote endpoint to which the socket will be * connected. Copies will be made of the endpoint object as required. diff --git a/libtorrent/include/libtorrent/asio/basic_socket_acceptor.hpp b/libtorrent/include/asio/basic_socket_acceptor.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/basic_socket_acceptor.hpp rename to libtorrent/include/asio/basic_socket_acceptor.hpp diff --git a/libtorrent/include/libtorrent/asio/basic_socket_iostream.hpp b/libtorrent/include/asio/basic_socket_iostream.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/basic_socket_iostream.hpp rename to libtorrent/include/asio/basic_socket_iostream.hpp diff --git a/libtorrent/include/libtorrent/asio/basic_socket_streambuf.hpp b/libtorrent/include/asio/basic_socket_streambuf.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/basic_socket_streambuf.hpp rename to libtorrent/include/asio/basic_socket_streambuf.hpp diff --git a/libtorrent/include/libtorrent/asio/basic_stream_socket.hpp b/libtorrent/include/asio/basic_stream_socket.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/basic_stream_socket.hpp rename to libtorrent/include/asio/basic_stream_socket.hpp diff --git a/libtorrent/include/libtorrent/asio/basic_streambuf.hpp b/libtorrent/include/asio/basic_streambuf.hpp similarity index 98% rename from libtorrent/include/libtorrent/asio/basic_streambuf.hpp rename to libtorrent/include/asio/basic_streambuf.hpp index 5b14f5ef8..41649cc43 100644 --- a/libtorrent/include/libtorrent/asio/basic_streambuf.hpp +++ b/libtorrent/include/asio/basic_streambuf.hpp @@ -100,11 +100,9 @@ public: /// Move the start of the get area by the specified number of characters. void consume(std::size_t n) { - while (n > 0) - { - sbumpc(); - --n; - } + if (gptr() + n > pptr()) + n = pptr() - gptr(); + gbump(static_cast(n)); } protected: diff --git a/libtorrent/include/libtorrent/asio/buffer.hpp b/libtorrent/include/asio/buffer.hpp similarity index 72% rename from libtorrent/include/libtorrent/asio/buffer.hpp rename to libtorrent/include/asio/buffer.hpp index 99fb1e2c8..7bd04a811 100644 --- a/libtorrent/include/libtorrent/asio/buffer.hpp +++ b/libtorrent/include/asio/buffer.hpp @@ -195,6 +195,12 @@ public: /// A random-access iterator type that may be used to read elements. typedef const mutable_buffer* const_iterator; + /// Construct to represent a given memory range. + mutable_buffers_1(void* data, std::size_t size) + : mutable_buffer(data, size) + { + } + /// Construct to represent a single modifiable buffer. explicit mutable_buffers_1(const mutable_buffer& b) : mutable_buffer(b) @@ -359,6 +365,12 @@ public: /// A random-access iterator type that may be used to read elements. typedef const const_buffer* const_iterator; + /// Construct to represent a given memory range. + const_buffers_1(const void* data, std::size_t size) + : const_buffer(data, size) + { + } + /// Construct to represent a single non-modifiable buffer. explicit const_buffers_1(const const_buffer& b) : const_buffer(b) @@ -378,6 +390,33 @@ public: } }; +/// An implementation of both the ConstBufferSequence and MutableBufferSequence +/// concepts to represent a null buffer sequence. +class null_buffers +{ +public: + /// The type for each element in the list of buffers. + typedef mutable_buffer value_type; + + /// A random-access iterator type that may be used to read elements. + typedef const mutable_buffer* const_iterator; + + /// Get a random-access iterator to the first element. + const_iterator begin() const + { + return &buf_; + } + + /// Get a random-access iterator for one past the last element. + const_iterator end() const + { + return &buf_; + } + +private: + mutable_buffer buf_; +}; + #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) namespace detail { @@ -415,12 +454,22 @@ private: /** @defgroup buffer asio::buffer * * @brief The asio::buffer function is used to create a buffer object to - * represent raw memory, an array of POD elements, or a vector of POD elements. + * represent raw memory, an array of POD elements, a vector of POD elements, + * or a std::string. + * + * A buffer object represents a contiguous region of memory as a 2-tuple + * consisting of a pointer and size in bytes. A tuple of the form {void*, + * size_t} specifies a mutable (modifiable) region of memory. Similarly, a + * tuple of the form {const void*, size_t} specifies a const + * (non-modifiable) region of memory. These two forms correspond to the classes + * mutable_buffer and const_buffer, respectively. To mirror C++'s conversion + * rules, a mutable_buffer is implicitly convertible to a const_buffer, and the + * opposite conversion is not permitted. * * The simplest use case involves reading or writing a single buffer of a * specified size: * - * @code sock.write(asio::buffer(data, size)); @endcode + * @code sock.send(asio::buffer(data, size)); @endcode * * In the above example, the return value of asio::buffer meets the * requirements of the ConstBufferSequence concept so that it may be directly @@ -432,13 +481,90 @@ private: * automatically determining the size of the buffer: * * @code char d1[128]; - * size_t bytes_transferred = sock.read(asio::buffer(d1)); + * size_t bytes_transferred = sock.receive(asio::buffer(d1)); * * std::vector d2(128); - * bytes_transferred = sock.read(asio::buffer(d2)); + * bytes_transferred = sock.receive(asio::buffer(d2)); * * boost::array d3; - * bytes_transferred = sock.read(asio::buffer(d3)); @endcode + * bytes_transferred = sock.receive(asio::buffer(d3)); @endcode + * + * In all three cases above, the buffers created are exactly 128 bytes long. + * Note that a vector is @e never automatically resized when creating or using + * a buffer. The buffer size is determined using the vector's size() + * member function, and not its capacity. + * + * @par Accessing Buffer Contents + * + * The contents of a buffer may be accessed using the asio::buffer_size + * and asio::buffer_cast functions: + * + * @code asio::mutable_buffer b1 = ...; + * std::size_t s1 = asio::buffer_size(b1); + * unsigned char* p1 = asio::buffer_cast(b1); + * + * asio::const_buffer b2 = ...; + * std::size_t s2 = asio::buffer_size(b2); + * const void* p2 = asio::buffer_cast(b2); @endcode + * + * The asio::buffer_cast function permits violations of type safety, so + * uses of it in application code should be carefully considered. + * + * @par Buffer Invalidation + * + * A buffer object does not have any ownership of the memory it refers to. It + * is the responsibility of the application to ensure the memory region remains + * valid until it is no longer required for an I/O operation. When the memory + * is no longer available, the buffer is said to have been invalidated. + * + * For the asio::buffer overloads that accept an argument of type + * std::vector, the buffer objects returned are invalidated by any vector + * operation that also invalidates all references, pointers and iterators + * referring to the elements in the sequence (C++ Std, 23.2.4) + * + * For the asio::buffer overloads that accept an argument of type + * std::string, the buffer objects returned are invalidated according to the + * rules defined for invalidation of references, pointers and iterators + * referring to elements of the sequence (C++ Std, 21.3). + * + * @par Buffer Arithmetic + * + * Buffer objects may be manipulated using simple arithmetic in a safe way + * which helps prevent buffer overruns. Consider an array initialised as + * follows: + * + * @code boost::array a = { 'a', 'b', 'c', 'd', 'e' }; @endcode + * + * A buffer object @c b1 created using: + * + * @code b1 = asio::buffer(a); @endcode + * + * represents the entire array, { 'a', 'b', 'c', 'd', 'e' }. An + * optional second argument to the asio::buffer function may be used to + * limit the size, in bytes, of the buffer: + * + * @code b2 = asio::buffer(a, 3); @endcode + * + * such that @c b2 represents the data { 'a', 'b', 'c' }. Even if the + * size argument exceeds the actual size of the array, the size of the buffer + * object created will be limited to the array size. + * + * An offset may be applied to an existing buffer to create a new one: + * + * @code b3 = b1 + 2; @endcode + * + * where @c b3 will set to represent { 'c', 'd', 'e' }. If the offset + * exceeds the size of the existing buffer, the newly created buffer will be + * empty. + * + * Both an offset and size may be specified to create a buffer that corresponds + * to a specific range of bytes within an existing buffer: + * + * @code b4 = asio::buffer(b1 + 1, 3); @endcode + * + * so that @c b4 will refer to the bytes { 'b', 'c', 'd' }. + * + * @par Buffers and Scatter-Gather I/O * * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple * buffer objects may be assigned into a container that supports the @@ -453,23 +579,32 @@ private: * asio::buffer(d1), * asio::buffer(d2), * asio::buffer(d3) }; - * bytes_transferred = sock.read(bufs1); + * bytes_transferred = sock.receive(bufs1); * * std::vector bufs2; * bufs2.push_back(asio::buffer(d1)); * bufs2.push_back(asio::buffer(d2)); * bufs2.push_back(asio::buffer(d3)); - * bytes_transferred = sock.write(bufs2); @endcode + * bytes_transferred = sock.send(bufs2); @endcode */ /*@{*/ /// Create a new modifiable buffer from an existing buffer. +/** + * @returns mutable_buffers_1(b). + */ inline mutable_buffers_1 buffer(const mutable_buffer& b) { return mutable_buffers_1(b); } /// Create a new modifiable buffer from an existing buffer. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * buffer_cast(b), + * min(buffer_size(b), max_size_in_bytes)); @endcode + */ inline mutable_buffers_1 buffer(const mutable_buffer& b, std::size_t max_size_in_bytes) { @@ -484,12 +619,21 @@ inline mutable_buffers_1 buffer(const mutable_buffer& b, } /// Create a new non-modifiable buffer from an existing buffer. +/** + * @returns const_buffers_1(b). + */ inline const_buffers_1 buffer(const const_buffer& b) { return const_buffers_1(b); } /// Create a new non-modifiable buffer from an existing buffer. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * buffer_cast(b), + * min(buffer_size(b), max_size_in_bytes)); @endcode + */ inline const_buffers_1 buffer(const const_buffer& b, std::size_t max_size_in_bytes) { @@ -504,12 +648,18 @@ inline const_buffers_1 buffer(const const_buffer& b, } /// Create a new modifiable buffer that represents the given memory range. +/** + * @returns mutable_buffers_1(data, size_in_bytes). + */ inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes) { return mutable_buffers_1(mutable_buffer(data, size_in_bytes)); } /// Create a new non-modifiable buffer that represents the given memory range. +/** + * @returns const_buffers_1(data, size_in_bytes). + */ inline const_buffers_1 buffer(const void* data, std::size_t size_in_bytes) { @@ -517,6 +667,12 @@ inline const_buffers_1 buffer(const void* data, } /// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * static_cast(data), + * N * sizeof(PodType)); @endcode + */ template inline mutable_buffers_1 buffer(PodType (&data)[N]) { @@ -524,6 +680,12 @@ inline mutable_buffers_1 buffer(PodType (&data)[N]) } /// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * static_cast(data), + * min(N * sizeof(PodType), max_size_in_bytes)); @endcode + */ template inline mutable_buffers_1 buffer(PodType (&data)[N], std::size_t max_size_in_bytes) @@ -535,6 +697,12 @@ inline mutable_buffers_1 buffer(PodType (&data)[N], } /// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * static_cast(data), + * N * sizeof(PodType)); @endcode + */ template inline const_buffers_1 buffer(const PodType (&data)[N]) { @@ -542,6 +710,12 @@ inline const_buffers_1 buffer(const PodType (&data)[N]) } /// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * static_cast(data), + * min(N * sizeof(PodType), max_size_in_bytes)); @endcode + */ template inline const_buffers_1 buffer(const PodType (&data)[N], std::size_t max_size_in_bytes) @@ -624,6 +798,12 @@ buffer(boost::array& data, std::size_t max_size_in_bytes) // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) /// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ template inline mutable_buffers_1 buffer(boost::array& data) { @@ -632,6 +812,12 @@ inline mutable_buffers_1 buffer(boost::array& data) } /// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ template inline mutable_buffers_1 buffer(boost::array& data, std::size_t max_size_in_bytes) @@ -643,6 +829,12 @@ inline mutable_buffers_1 buffer(boost::array& data, } /// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ template inline const_buffers_1 buffer(boost::array& data) { @@ -651,6 +843,12 @@ inline const_buffers_1 buffer(boost::array& data) } /// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ template inline const_buffers_1 buffer(boost::array& data, std::size_t max_size_in_bytes) @@ -665,6 +863,12 @@ inline const_buffers_1 buffer(boost::array& data, // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) /// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ template inline const_buffers_1 buffer(const boost::array& data) { @@ -673,6 +877,12 @@ inline const_buffers_1 buffer(const boost::array& data) } /// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ template inline const_buffers_1 buffer(const boost::array& data, std::size_t max_size_in_bytes) @@ -685,6 +895,11 @@ inline const_buffers_1 buffer(const boost::array& data, /// Create a new modifiable buffer that represents the given POD vector. /** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.size() ? &data[0] : 0, + * data.size() * sizeof(PodType)); @endcode + * * @note The buffer is invalidated by any vector operation that would also * invalidate iterators. */ @@ -692,7 +907,7 @@ template inline mutable_buffers_1 buffer(std::vector& data) { return mutable_buffers_1( - mutable_buffer(&data[0], data.size() * sizeof(PodType) + mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) , detail::buffer_debug_check< typename std::vector::iterator @@ -703,6 +918,11 @@ inline mutable_buffers_1 buffer(std::vector& data) /// Create a new modifiable buffer that represents the given POD vector. /** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.size() ? &data[0] : 0, + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + * * @note The buffer is invalidated by any vector operation that would also * invalidate iterators. */ @@ -711,7 +931,7 @@ inline mutable_buffers_1 buffer(std::vector& data, std::size_t max_size_in_bytes) { return mutable_buffers_1( - mutable_buffer(&data[0], + mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) < max_size_in_bytes ? data.size() * sizeof(PodType) : max_size_in_bytes #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) @@ -724,6 +944,11 @@ inline mutable_buffers_1 buffer(std::vector& data, /// Create a new non-modifiable buffer that represents the given POD vector. /** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.size() ? &data[0] : 0, + * data.size() * sizeof(PodType)); @endcode + * * @note The buffer is invalidated by any vector operation that would also * invalidate iterators. */ @@ -732,7 +957,7 @@ inline const_buffers_1 buffer( const std::vector& data) { return const_buffers_1( - const_buffer(&data[0], data.size() * sizeof(PodType) + const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) , detail::buffer_debug_check< typename std::vector::const_iterator @@ -743,6 +968,11 @@ inline const_buffers_1 buffer( /// Create a new non-modifiable buffer that represents the given POD vector. /** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.size() ? &data[0] : 0, + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + * * @note The buffer is invalidated by any vector operation that would also * invalidate iterators. */ @@ -751,7 +981,7 @@ inline const_buffers_1 buffer( const std::vector& data, std::size_t max_size_in_bytes) { return const_buffers_1( - const_buffer(&data[0], + const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) < max_size_in_bytes ? data.size() * sizeof(PodType) : max_size_in_bytes #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) @@ -764,6 +994,8 @@ inline const_buffers_1 buffer( /// Create a new non-modifiable buffer that represents the given string. /** + * @returns const_buffers_1(data.data(), data.size()). + * * @note The buffer is invalidated by any non-const operation called on the * given string object. */ @@ -778,6 +1010,11 @@ inline const_buffers_1 buffer(const std::string& data) /// Create a new non-modifiable buffer that represents the given string. /** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size(), max_size_in_bytes)); @endcode + * * @note The buffer is invalidated by any non-const operation called on the * given string object. */ diff --git a/libtorrent/include/libtorrent/asio/buffered_read_stream.hpp b/libtorrent/include/asio/buffered_read_stream.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/buffered_read_stream.hpp rename to libtorrent/include/asio/buffered_read_stream.hpp diff --git a/libtorrent/include/libtorrent/asio/buffered_read_stream_fwd.hpp b/libtorrent/include/asio/buffered_read_stream_fwd.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/buffered_read_stream_fwd.hpp rename to libtorrent/include/asio/buffered_read_stream_fwd.hpp diff --git a/libtorrent/include/libtorrent/asio/buffered_stream.hpp b/libtorrent/include/asio/buffered_stream.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/buffered_stream.hpp rename to libtorrent/include/asio/buffered_stream.hpp diff --git a/libtorrent/include/libtorrent/asio/buffered_stream_fwd.hpp b/libtorrent/include/asio/buffered_stream_fwd.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/buffered_stream_fwd.hpp rename to libtorrent/include/asio/buffered_stream_fwd.hpp diff --git a/libtorrent/include/libtorrent/asio/buffered_write_stream.hpp b/libtorrent/include/asio/buffered_write_stream.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/buffered_write_stream.hpp rename to libtorrent/include/asio/buffered_write_stream.hpp diff --git a/libtorrent/include/libtorrent/asio/buffered_write_stream_fwd.hpp b/libtorrent/include/asio/buffered_write_stream_fwd.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/buffered_write_stream_fwd.hpp rename to libtorrent/include/asio/buffered_write_stream_fwd.hpp diff --git a/libtorrent/include/asio/buffers_iterator.hpp b/libtorrent/include/asio/buffers_iterator.hpp new file mode 100644 index 000000000..cc13bb5e2 --- /dev/null +++ b/libtorrent/include/asio/buffers_iterator.hpp @@ -0,0 +1,318 @@ +// +// buffers_iterator.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BUFFERS_ITERATOR_HPP +#define ASIO_BUFFERS_ITERATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include +#include +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/buffer.hpp" + +namespace asio { + +namespace detail +{ + template + struct buffers_iterator_types_helper; + + template <> + struct buffers_iterator_types_helper + { + typedef const_buffer buffer_type; + template + struct byte_type + { + typedef typename boost::add_const::type type; + }; + }; + + template <> + struct buffers_iterator_types_helper + { + typedef mutable_buffer buffer_type; + template + struct byte_type + { + typedef ByteType type; + }; + }; + + template + struct buffers_iterator_types + { + enum + { + is_mutable = boost::is_convertible< + typename BufferSequence::value_type, mutable_buffer>::value + }; + typedef buffers_iterator_types_helper helper; + typedef typename helper::buffer_type buffer_type; + typedef typename helper::template byte_type::type byte_type; + }; +} + +/// A random access iterator over the bytes in a buffer sequence. +template +class buffers_iterator + : public boost::iterator_facade< + buffers_iterator, + typename detail::buffers_iterator_types< + BufferSequence, ByteType>::byte_type, + boost::random_access_traversal_tag> +{ +private: + typedef typename detail::buffers_iterator_types< + BufferSequence, ByteType>::buffer_type buffer_type; + typedef typename detail::buffers_iterator_types< + BufferSequence, ByteType>::byte_type byte_type; + +public: + /// Default constructor. Creates an iterator in an undefined state. + buffers_iterator() + : current_buffer_(), + current_buffer_position_(0), + begin_(), + current_(), + end_(), + position_(0) + { + } + + /// Construct an iterator representing the beginning of the buffers' data. + static buffers_iterator begin(const BufferSequence& buffers) + { + buffers_iterator new_iter; + new_iter.begin_ = buffers.begin(); + new_iter.current_ = buffers.begin(); + new_iter.end_ = buffers.end(); + while (new_iter.current_ != new_iter.end_) + { + new_iter.current_buffer_ = *new_iter.current_; + if (asio::buffer_size(new_iter.current_buffer_) > 0) + break; + ++new_iter.current_; + } + return new_iter; + } + + /// Construct an iterator representing the end of the buffers' data. + static buffers_iterator end(const BufferSequence& buffers) + { + buffers_iterator new_iter; + new_iter.begin_ = buffers.begin(); + new_iter.current_ = buffers.begin(); + new_iter.end_ = buffers.end(); + while (new_iter.current_ != new_iter.end_) + { + buffer_type buffer = *new_iter.current_; + new_iter.position_ += asio::buffer_size(buffer); + ++new_iter.current_; + } + return new_iter; + } + +private: + friend class boost::iterator_core_access; + + // Dereference the iterator. + byte_type& dereference() const + { + return buffer_cast(current_buffer_)[current_buffer_position_]; + } + + // Compare two iterators for equality. + bool equal(const buffers_iterator& other) const + { + return position_ == other.position_; + } + + // Increment the iterator. + void increment() + { + BOOST_ASSERT(current_ != end_ && "iterator out of bounds"); + ++position_; + + // Check if the increment can be satisfied by the current buffer. + ++current_buffer_position_; + if (current_buffer_position_ != asio::buffer_size(current_buffer_)) + return; + + // Find the next non-empty buffer. + ++current_; + current_buffer_position_ = 0; + while (current_ != end_) + { + current_buffer_ = *current_; + if (asio::buffer_size(current_buffer_) > 0) + return; + ++current_; + } + } + + // Decrement the iterator. + void decrement() + { + BOOST_ASSERT(position_ > 0 && "iterator out of bounds"); + --position_; + + // Check if the decrement can be satisfied by the current buffer. + if (current_buffer_position_ != 0) + { + --current_buffer_position_; + return; + } + + // Find the previous non-empty buffer. + typename BufferSequence::const_iterator iter = current_; + while (iter != begin_) + { + --iter; + buffer_type buffer = *iter; + std::size_t buffer_size = asio::buffer_size(buffer); + if (buffer_size > 0) + { + current_ = iter; + current_buffer_ = buffer; + current_buffer_position_ = buffer_size - 1; + return; + } + } + } + + // Advance the iterator by the specified distance. + void advance(std::ptrdiff_t n) + { + if (n > 0) + { + BOOST_ASSERT(current_ != end_ && "iterator out of bounds"); + for (;;) + { + std::ptrdiff_t current_buffer_balance + = asio::buffer_size(current_buffer_) + - current_buffer_position_; + + // Check if the advance can be satisfied by the current buffer. + if (current_buffer_balance > n) + { + position_ += n; + current_buffer_position_ += n; + return; + } + + // Update position. + n -= current_buffer_balance; + position_ += current_buffer_balance; + + // Move to next buffer. If it is empty then it will be skipped on the + // next iteration of this loop. + if (++current_ == end_) + { + BOOST_ASSERT(n == 0 && "iterator out of bounds"); + current_buffer_ = buffer_type(); + current_buffer_position_ = 0; + return; + } + current_buffer_ = *current_; + current_buffer_position_ = 0; + } + } + else if (n < 0) + { + std::size_t abs_n = -n; + BOOST_ASSERT(position_ >= abs_n && "iterator out of bounds"); + for (;;) + { + // Check if the advance can be satisfied by the current buffer. + if (current_buffer_position_ >= abs_n) + { + position_ -= abs_n; + current_buffer_position_ -= abs_n; + return; + } + + // Update position. + abs_n -= current_buffer_position_; + position_ -= current_buffer_position_; + + // Check if we've reached the beginning of the buffers. + if (current_ == begin_) + { + BOOST_ASSERT(abs_n == 0 && "iterator out of bounds"); + current_buffer_position_ = 0; + return; + } + + // Find the previous non-empty buffer. + typename BufferSequence::const_iterator iter = current_; + while (iter != begin_) + { + --iter; + buffer_type buffer = *iter; + std::size_t buffer_size = asio::buffer_size(buffer); + if (buffer_size > 0) + { + current_ = iter; + current_buffer_ = buffer; + current_buffer_position_ = buffer_size; + break; + } + } + } + } + } + + // Determine the distance between two iterators. + std::ptrdiff_t distance_to(const buffers_iterator& other) const + { + return other.position_ - position_; + } + + buffer_type current_buffer_; + std::size_t current_buffer_position_; + typename BufferSequence::const_iterator begin_; + typename BufferSequence::const_iterator current_; + typename BufferSequence::const_iterator end_; + std::size_t position_; +}; + +/// Construct an iterator representing the beginning of the buffers' data. +template +inline buffers_iterator buffers_begin( + const BufferSequence& buffers) +{ + return buffers_iterator::begin(buffers); +} + +/// Construct an iterator representing the end of the buffers' data. +template +inline buffers_iterator buffers_end( + const BufferSequence& buffers) +{ + return buffers_iterator::end(buffers); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BUFFERS_ITERATOR_HPP diff --git a/libtorrent/include/libtorrent/asio/completion_condition.hpp b/libtorrent/include/asio/completion_condition.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/completion_condition.hpp rename to libtorrent/include/asio/completion_condition.hpp diff --git a/libtorrent/include/libtorrent/asio/datagram_socket_service.hpp b/libtorrent/include/asio/datagram_socket_service.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/datagram_socket_service.hpp rename to libtorrent/include/asio/datagram_socket_service.hpp diff --git a/libtorrent/include/libtorrent/asio/deadline_timer.hpp b/libtorrent/include/asio/deadline_timer.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/deadline_timer.hpp rename to libtorrent/include/asio/deadline_timer.hpp diff --git a/libtorrent/include/libtorrent/asio/deadline_timer_service.hpp b/libtorrent/include/asio/deadline_timer_service.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/deadline_timer_service.hpp rename to libtorrent/include/asio/deadline_timer_service.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/bind_handler.hpp b/libtorrent/include/asio/detail/bind_handler.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/bind_handler.hpp rename to libtorrent/include/asio/detail/bind_handler.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/buffer_resize_guard.hpp b/libtorrent/include/asio/detail/buffer_resize_guard.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/buffer_resize_guard.hpp rename to libtorrent/include/asio/detail/buffer_resize_guard.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/buffered_stream_storage.hpp b/libtorrent/include/asio/detail/buffered_stream_storage.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/buffered_stream_storage.hpp rename to libtorrent/include/asio/detail/buffered_stream_storage.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/call_stack.hpp b/libtorrent/include/asio/detail/call_stack.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/call_stack.hpp rename to libtorrent/include/asio/detail/call_stack.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/const_buffers_iterator.hpp b/libtorrent/include/asio/detail/const_buffers_iterator.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/const_buffers_iterator.hpp rename to libtorrent/include/asio/detail/const_buffers_iterator.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/consuming_buffers.hpp b/libtorrent/include/asio/detail/consuming_buffers.hpp similarity index 92% rename from libtorrent/include/libtorrent/asio/detail/consuming_buffers.hpp rename to libtorrent/include/asio/detail/consuming_buffers.hpp index d598b0129..8e88e361d 100644 --- a/libtorrent/include/libtorrent/asio/detail/consuming_buffers.hpp +++ b/libtorrent/include/asio/detail/consuming_buffers.hpp @@ -24,6 +24,8 @@ #include #include "asio/detail/pop_options.hpp" +#include "asio/buffer.hpp" + namespace asio { namespace detail { @@ -197,6 +199,24 @@ private: typename Buffers::const_iterator begin_remainder_; }; +// Specialisation for null_buffers to ensure that the null_buffers type is +// always passed through to the underlying read or write operation. +template +class consuming_buffers + : public asio::null_buffers +{ +public: + consuming_buffers(const asio::null_buffers&) + { + // No-op. + } + + void consume(std::size_t) + { + // No-op. + } +}; + } // namespace detail } // namespace asio diff --git a/libtorrent/include/libtorrent/asio/detail/deadline_timer_service.hpp b/libtorrent/include/asio/detail/deadline_timer_service.hpp similarity index 94% rename from libtorrent/include/libtorrent/asio/detail/deadline_timer_service.hpp rename to libtorrent/include/asio/detail/deadline_timer_service.hpp index 1acbd15e4..6f30d7546 100644 --- a/libtorrent/include/libtorrent/asio/detail/deadline_timer_service.hpp +++ b/libtorrent/include/asio/detail/deadline_timer_service.hpp @@ -26,6 +26,7 @@ #include "asio/error.hpp" #include "asio/io_service.hpp" #include "asio/detail/bind_handler.hpp" +#include "asio/detail/handler_base_from_member.hpp" #include "asio/detail/noncopyable.hpp" #include "asio/detail/service_base.hpp" #include "asio/detail/socket_ops.hpp" @@ -153,25 +154,25 @@ public: } template - class wait_handler + class wait_handler : + public handler_base_from_member { public: wait_handler(asio::io_service& io_service, Handler handler) - : io_service_(io_service), - work_(io_service), - handler_(handler) + : handler_base_from_member(handler), + io_service_(io_service), + work_(io_service) { } void operator()(const asio::error_code& result) { - io_service_.post(detail::bind_handler(handler_, result)); + io_service_.post(detail::bind_handler(this->handler_, result)); } private: asio::io_service& io_service_; asio::io_service::work work_; - Handler handler_; }; // Start an asynchronous wait on the timer. diff --git a/libtorrent/include/asio/detail/descriptor_ops.hpp b/libtorrent/include/asio/detail/descriptor_ops.hpp new file mode 100644 index 000000000..6de34f621 --- /dev/null +++ b/libtorrent/include/asio/detail/descriptor_ops.hpp @@ -0,0 +1,138 @@ +// +// descriptor_ops.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_DESCRIPTOR_OPS_HPP +#define ASIO_DETAIL_DESCRIPTOR_OPS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/error.hpp" +#include "asio/detail/socket_types.hpp" + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +namespace asio { +namespace detail { +namespace descriptor_ops { + +inline void clear_error(asio::error_code& ec) +{ + errno = 0; + ec = asio::error_code(); +} + +template +inline ReturnType error_wrapper(ReturnType return_value, + asio::error_code& ec) +{ + ec = asio::error_code(errno, + asio::error::get_system_category()); + return return_value; +} + +inline int open(const char* path, int flags, asio::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::open(path, flags), ec); +} + +inline int close(int d, asio::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::close(d), ec); +} + +typedef iovec buf; + +inline void init_buf(buf& b, void* data, size_t size) +{ + b.iov_base = data; + b.iov_len = size; +} + +inline void init_buf(buf& b, const void* data, size_t size) +{ + b.iov_base = const_cast(data); + b.iov_len = size; +} + +inline int scatter_read(int d, buf* bufs, size_t count, + asio::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::readv(d, bufs, static_cast(count)), ec); +} + +inline int gather_write(int d, const buf* bufs, size_t count, + asio::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::writev(d, bufs, static_cast(count)), ec); +} + +inline int ioctl(int d, long cmd, ioctl_arg_type* arg, + asio::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::ioctl(d, cmd, arg), ec); +} + +inline int fcntl(int d, long cmd, asio::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::fcntl(d, cmd), ec); +} + +inline int fcntl(int d, long cmd, long arg, asio::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::fcntl(d, cmd, arg), ec); +} + +inline int poll_read(int d, asio::error_code& ec) +{ + clear_error(ec); + pollfd fds; + fds.fd = d; + fds.events = POLLIN; + fds.revents = 0; + clear_error(ec); + return error_wrapper(::poll(&fds, 1, -1), ec); +} + +inline int poll_write(int d, asio::error_code& ec) +{ + clear_error(ec); + pollfd fds; + fds.fd = d; + fds.events = POLLOUT; + fds.revents = 0; + clear_error(ec); + return error_wrapper(::poll(&fds, 1, -1), ec); +} + +} // namespace descriptor_ops +} // namespace detail +} // namespace asio + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_DESCRIPTOR_OPS_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/dev_poll_reactor.hpp b/libtorrent/include/asio/detail/dev_poll_reactor.hpp similarity index 86% rename from libtorrent/include/libtorrent/asio/detail/dev_poll_reactor.hpp rename to libtorrent/include/asio/detail/dev_poll_reactor.hpp index 1f24c5a1a..d68d8fe72 100644 --- a/libtorrent/include/libtorrent/asio/detail/dev_poll_reactor.hpp +++ b/libtorrent/include/asio/detail/dev_poll_reactor.hpp @@ -53,6 +53,11 @@ class dev_poll_reactor : public asio::detail::service_base > { public: + // Per-descriptor data. + struct per_descriptor_data + { + }; + // Constructor. dev_poll_reactor(asio::io_service& io_service) : asio::detail::service_base< @@ -115,11 +120,11 @@ public: for (std::size_t i = 0; i < timer_queues_.size(); ++i) timer_queues_[i]->destroy_timers(); timer_queues_.clear(); - } + } // Register a socket with the reactor. Returns 0 on success, system error // code on failure. - int register_descriptor(socket_type descriptor) + int register_descriptor(socket_type, per_descriptor_data&) { return 0; } @@ -127,16 +132,27 @@ public: // Start a new read operation. The handler object will be invoked when the // given descriptor is ready to be read, or an error has occurred. template - void start_read_op(socket_type descriptor, Handler handler) + void start_read_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool allow_speculative_read = true) { asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!read_op_queue_.has_operation(descriptor)) - if (handler(asio::error_code())) - return; + if (allow_speculative_read) + { + if (!read_op_queue_.has_operation(descriptor)) + { + asio::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + } + } if (read_op_queue_.enqueue_operation(descriptor, handler)) { @@ -153,16 +169,27 @@ public: // Start a new write operation. The handler object will be invoked when the // given descriptor is ready to be written, or an error has occurred. template - void start_write_op(socket_type descriptor, Handler handler) + void start_write_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool allow_speculative_write = true) { asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!write_op_queue_.has_operation(descriptor)) - if (handler(asio::error_code())) - return; + if (allow_speculative_write) + { + if (!write_op_queue_.has_operation(descriptor)) + { + asio::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + } + } if (write_op_queue_.enqueue_operation(descriptor, handler)) { @@ -179,7 +206,8 @@ public: // Start a new exception operation. The handler object will be invoked when // the given descriptor has exception information, or an error has occurred. template - void start_except_op(socket_type descriptor, Handler handler) + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { asio::detail::mutex::scoped_lock lock(mutex_); @@ -198,26 +226,25 @@ public: } } - // Start new write and exception operations. The handler object will be - // invoked when the given descriptor is ready for writing or has exception + // Start a new write operation. The handler object will be invoked when the // information available, or an error has occurred. template - void start_write_and_except_ops(socket_type descriptor, Handler handler) + void start_connect_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - bool need_mod = write_op_queue_.enqueue_operation(descriptor, handler); - need_mod = except_op_queue_.enqueue_operation(descriptor, handler) - && need_mod; - if (need_mod) + if (write_op_queue_.enqueue_operation(descriptor, handler)) { ::pollfd& ev = add_pending_event_change(descriptor); - ev.events = POLLOUT | POLLPRI | POLLERR | POLLHUP; + ev.events = POLLOUT | POLLERR | POLLHUP; if (read_op_queue_.has_operation(descriptor)) ev.events |= POLLIN; + if (except_op_queue_.has_operation(descriptor)) + ev.events |= POLLPRI; interrupter_.interrupt(); } } @@ -225,25 +252,15 @@ public: // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. - void cancel_ops(socket_type descriptor) + void cancel_ops(socket_type descriptor, per_descriptor_data&) { asio::detail::mutex::scoped_lock lock(mutex_); cancel_ops_unlocked(descriptor); } - // Enqueue cancellation of all operations associated with the given - // descriptor. The handlers associated with the descriptor will be invoked - // with the operation_aborted error. This function does not acquire the - // dev_poll_reactor's mutex, and so should only be used from within a reactor - // handler. - void enqueue_cancel_ops_unlocked(socket_type descriptor) - { - pending_cancellations_.push_back(descriptor); - } - // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. - void close_descriptor(socket_type descriptor) + void close_descriptor(socket_type descriptor, per_descriptor_data&) { asio::detail::mutex::scoped_lock lock(mutex_); @@ -313,16 +330,16 @@ private: // Dispatch any operation cancellations that were made while the select // loop was not running. - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) timer_queues_[i]->dispatch_cancellations(); // Check if the thread is supposed to stop. if (stop_thread_) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -331,7 +348,7 @@ private: if (!block && read_op_queue_.empty() && write_op_queue_.empty() && except_op_queue_.empty() && all_timer_queues_are_empty()) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -347,9 +364,9 @@ private: int descriptor = pending_event_changes_[i].fd; asio::error_code ec = asio::error_code( errno, asio::error::get_system_category()); - read_op_queue_.dispatch_all_operations(descriptor, ec); - write_op_queue_.dispatch_all_operations(descriptor, ec); - except_op_queue_.dispatch_all_operations(descriptor, ec); + read_op_queue_.perform_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); } } pending_event_changes_.clear(); @@ -370,7 +387,7 @@ private: lock.lock(); wait_in_progress_ = false; - // Block signals while dispatching operations. + // Block signals while performing operations. asio::detail::signal_blocker sb; // Dispatch the waiting events. @@ -391,17 +408,17 @@ private: // Exception operations must be processed first to ensure that any // out-of-band data is read before normal data. if (events[i].events & (POLLPRI | POLLERR | POLLHUP)) - more_except = except_op_queue_.dispatch_operation(descriptor, ec); + more_except = except_op_queue_.perform_operation(descriptor, ec); else more_except = except_op_queue_.has_operation(descriptor); if (events[i].events & (POLLIN | POLLERR | POLLHUP)) - more_reads = read_op_queue_.dispatch_operation(descriptor, ec); + more_reads = read_op_queue_.perform_operation(descriptor, ec); else more_reads = read_op_queue_.has_operation(descriptor); if (events[i].events & (POLLOUT | POLLERR | POLLHUP)) - more_writes = write_op_queue_.dispatch_operation(descriptor, ec); + more_writes = write_op_queue_.perform_operation(descriptor, ec); else more_writes = write_op_queue_.has_operation(descriptor); @@ -436,16 +453,16 @@ private: { ec = asio::error_code(errno, asio::error::get_system_category()); - read_op_queue_.dispatch_all_operations(descriptor, ec); - write_op_queue_.dispatch_all_operations(descriptor, ec); - except_op_queue_.dispatch_all_operations(descriptor, ec); + read_op_queue_.perform_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); } } } } - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) { timer_queues_[i]->dispatch_timers(); @@ -457,7 +474,7 @@ private: cancel_ops_unlocked(pending_cancellations_[i]); pending_cancellations_.clear(); - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); } // Run the select loop in the thread. @@ -557,16 +574,16 @@ private: // destructors may make calls back into this reactor. We make a copy of the // vector of timer queues since the original may be modified while the lock // is not held. - void cleanup_operations_and_timers( + void complete_operations_and_timers( asio::detail::mutex::scoped_lock& lock) { timer_queues_for_cleanup_ = timer_queues_; lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->cleanup_timers(); + timer_queues_for_cleanup_[i]->complete_timers(); } // Add a pending event entry for the given descriptor. diff --git a/libtorrent/include/libtorrent/asio/detail/dev_poll_reactor_fwd.hpp b/libtorrent/include/asio/detail/dev_poll_reactor_fwd.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/dev_poll_reactor_fwd.hpp rename to libtorrent/include/asio/detail/dev_poll_reactor_fwd.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/epoll_reactor.hpp b/libtorrent/include/asio/detail/epoll_reactor.hpp similarity index 79% rename from libtorrent/include/libtorrent/asio/detail/epoll_reactor.hpp rename to libtorrent/include/asio/detail/epoll_reactor.hpp index e318ed666..b8fd6afb8 100644 --- a/libtorrent/include/libtorrent/asio/detail/epoll_reactor.hpp +++ b/libtorrent/include/asio/detail/epoll_reactor.hpp @@ -53,6 +53,13 @@ class epoll_reactor : public asio::detail::service_base > { public: + // Per-descriptor data. + struct per_descriptor_data + { + bool allow_speculative_read; + bool allow_speculative_write; + }; + // Constructor. epoll_reactor(asio::io_service& io_service) : asio::detail::service_base >(io_service), @@ -118,10 +125,14 @@ public: // Register a socket with the reactor. Returns 0 on success, system error // code on failure. - int register_descriptor(socket_type descriptor) + int register_descriptor(socket_type descriptor, + per_descriptor_data& descriptor_data) { // No need to lock according to epoll documentation. + descriptor_data.allow_speculative_read = true; + descriptor_data.allow_speculative_write = true; + epoll_event ev = { 0, { 0 } }; ev.events = 0; ev.data.fd = descriptor; @@ -134,16 +145,47 @@ public: // Start a new read operation. The handler object will be invoked when the // given descriptor is ready to be read, or an error has occurred. template - void start_read_op(socket_type descriptor, Handler handler) + void start_read_op(socket_type descriptor, + per_descriptor_data& descriptor_data, + Handler handler, bool allow_speculative_read = true) { + if (allow_speculative_read && descriptor_data.allow_speculative_read) + { + asio::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative read in this function. + allow_speculative_read = false; + } + asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!read_op_queue_.has_operation(descriptor)) - if (handler(asio::error_code())) + if (!allow_speculative_read) + need_epoll_wait_ = true; + else if (!read_op_queue_.has_operation(descriptor)) + { + // Speculative reads are ok as there are no queued read operations. + descriptor_data.allow_speculative_read = true; + + asio::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); return; + } + } + + // Speculative reads are not ok as there will be queued read operations. + descriptor_data.allow_speculative_read = false; if (read_op_queue_.enqueue_operation(descriptor, handler)) { @@ -162,7 +204,7 @@ public: { asio::error_code ec(errno, asio::error::get_system_category()); - read_op_queue_.dispatch_all_operations(descriptor, ec); + read_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -170,16 +212,47 @@ public: // Start a new write operation. The handler object will be invoked when the // given descriptor is ready to be written, or an error has occurred. template - void start_write_op(socket_type descriptor, Handler handler) + void start_write_op(socket_type descriptor, + per_descriptor_data& descriptor_data, + Handler handler, bool allow_speculative_write = true) { + if (allow_speculative_write && descriptor_data.allow_speculative_write) + { + asio::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative write in this function. + allow_speculative_write = false; + } + asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!write_op_queue_.has_operation(descriptor)) - if (handler(asio::error_code())) + if (!allow_speculative_write) + need_epoll_wait_ = true; + else if (!write_op_queue_.has_operation(descriptor)) + { + // Speculative writes are ok as there are no queued write operations. + descriptor_data.allow_speculative_write = true; + + asio::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); return; + } + } + + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; if (write_op_queue_.enqueue_operation(descriptor, handler)) { @@ -198,7 +271,7 @@ public: { asio::error_code ec(errno, asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -206,7 +279,8 @@ public: // Start a new exception operation. The handler object will be invoked when // the given descriptor has exception information, or an error has occurred. template - void start_except_op(socket_type descriptor, Handler handler) + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { asio::detail::mutex::scoped_lock lock(mutex_); @@ -230,31 +304,34 @@ public: { asio::error_code ec(errno, asio::error::get_system_category()); - except_op_queue_.dispatch_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); } } } - // Start new write and exception operations. The handler object will be - // invoked when the given descriptor is ready for writing or has exception - // information available, or an error has occurred. + // Start a new write operation. The handler object will be invoked when the + // given descriptor is ready for writing or an error has occurred. Speculative + // writes are not allowed. template - void start_write_and_except_ops(socket_type descriptor, Handler handler) + void start_connect_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler) { asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - bool need_mod = write_op_queue_.enqueue_operation(descriptor, handler); - need_mod = except_op_queue_.enqueue_operation(descriptor, handler) - && need_mod; - if (need_mod) + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; + + if (write_op_queue_.enqueue_operation(descriptor, handler)) { epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLOUT | EPOLLPRI | EPOLLERR | EPOLLHUP; + ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP; if (read_op_queue_.has_operation(descriptor)) ev.events |= EPOLLIN; + if (except_op_queue_.has_operation(descriptor)) + ev.events |= EPOLLPRI; ev.data.fd = descriptor; int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); @@ -264,8 +341,7 @@ public: { asio::error_code ec(errno, asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, ec); - except_op_queue_.dispatch_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -273,25 +349,15 @@ public: // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. - void cancel_ops(socket_type descriptor) + void cancel_ops(socket_type descriptor, per_descriptor_data&) { asio::detail::mutex::scoped_lock lock(mutex_); cancel_ops_unlocked(descriptor); } - // Enqueue cancellation of all operations associated with the given - // descriptor. The handlers associated with the descriptor will be invoked - // with the operation_aborted error. This function does not acquire the - // epoll_reactor's mutex, and so should only be used from within a reactor - // handler. - void enqueue_cancel_ops_unlocked(socket_type descriptor) - { - pending_cancellations_.push_back(descriptor); - } - // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. - void close_descriptor(socket_type descriptor) + void close_descriptor(socket_type descriptor, per_descriptor_data&) { asio::detail::mutex::scoped_lock lock(mutex_); @@ -360,16 +426,16 @@ private: // Dispatch any operation cancellations that were made while the select // loop was not running. - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) timer_queues_[i]->dispatch_cancellations(); // Check if the thread is supposed to stop. if (stop_thread_) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -378,7 +444,7 @@ private: if (!block && read_op_queue_.empty() && write_op_queue_.empty() && except_op_queue_.empty() && all_timer_queues_are_empty()) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -395,7 +461,7 @@ private: lock.lock(); wait_in_progress_ = false; - // Block signals while dispatching operations. + // Block signals while performing operations. asio::detail::signal_blocker sb; // Dispatch the waiting events. @@ -416,17 +482,17 @@ private: // Exception operations must be processed first to ensure that any // out-of-band data is read before normal data. if (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)) - more_except = except_op_queue_.dispatch_operation(descriptor, ec); + more_except = except_op_queue_.perform_operation(descriptor, ec); else more_except = except_op_queue_.has_operation(descriptor); if (events[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP)) - more_reads = read_op_queue_.dispatch_operation(descriptor, ec); + more_reads = read_op_queue_.perform_operation(descriptor, ec); else more_reads = read_op_queue_.has_operation(descriptor); if (events[i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) - more_writes = write_op_queue_.dispatch_operation(descriptor, ec); + more_writes = write_op_queue_.perform_operation(descriptor, ec); else more_writes = write_op_queue_.has_operation(descriptor); @@ -460,16 +526,16 @@ private: { ec = asio::error_code(errno, asio::error::get_system_category()); - read_op_queue_.dispatch_all_operations(descriptor, ec); - write_op_queue_.dispatch_all_operations(descriptor, ec); - except_op_queue_.dispatch_all_operations(descriptor, ec); + read_op_queue_.perform_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); } } } } - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) { timer_queues_[i]->dispatch_timers(); @@ -485,7 +551,7 @@ private: need_epoll_wait_ = !read_op_queue_.empty() || !write_op_queue_.empty() || !except_op_queue_.empty(); - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); } // Run the select loop in the thread. @@ -588,16 +654,16 @@ private: // destructors may make calls back into this reactor. We make a copy of the // vector of timer queues since the original may be modified while the lock // is not held. - void cleanup_operations_and_timers( + void complete_operations_and_timers( asio::detail::mutex::scoped_lock& lock) { timer_queues_for_cleanup_ = timer_queues_; lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->cleanup_timers(); + timer_queues_for_cleanup_[i]->complete_timers(); } // Mutex to protect access to internal data. diff --git a/libtorrent/include/libtorrent/asio/detail/epoll_reactor_fwd.hpp b/libtorrent/include/asio/detail/epoll_reactor_fwd.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/epoll_reactor_fwd.hpp rename to libtorrent/include/asio/detail/epoll_reactor_fwd.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/event.hpp b/libtorrent/include/asio/detail/event.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/event.hpp rename to libtorrent/include/asio/detail/event.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/fd_set_adapter.hpp b/libtorrent/include/asio/detail/fd_set_adapter.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/fd_set_adapter.hpp rename to libtorrent/include/asio/detail/fd_set_adapter.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/handler_alloc_helpers.hpp b/libtorrent/include/asio/detail/handler_alloc_helpers.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/handler_alloc_helpers.hpp rename to libtorrent/include/asio/detail/handler_alloc_helpers.hpp diff --git a/libtorrent/include/asio/detail/handler_base_from_member.hpp b/libtorrent/include/asio/detail/handler_base_from_member.hpp new file mode 100644 index 000000000..87e16c14b --- /dev/null +++ b/libtorrent/include/asio/detail/handler_base_from_member.hpp @@ -0,0 +1,76 @@ +// +// handler_base_from_member.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP +#define ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" + +namespace asio { +namespace detail { + +// Base class for classes that need a handler data member. Forwards the custom +// allocation and invocation hooks to the contained handler. +template +class handler_base_from_member +{ +public: + handler_base_from_member(Handler handler) + : handler_(handler) + { + } + +//protected: + Handler handler_; + +protected: + // Protected destructor to prevent deletion through this type. + ~handler_base_from_member() + { + } +}; + +template +inline void* asio_handler_allocate(std::size_t size, + handler_base_from_member* this_handler) +{ + return asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + handler_base_from_member* this_handler) +{ + asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); +} + +template +inline void asio_handler_invoke(const Function& function, + handler_base_from_member* this_handler) +{ + asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/handler_invoke_helpers.hpp b/libtorrent/include/asio/detail/handler_invoke_helpers.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/handler_invoke_helpers.hpp rename to libtorrent/include/asio/detail/handler_invoke_helpers.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/handler_queue.hpp b/libtorrent/include/asio/detail/handler_queue.hpp similarity index 91% rename from libtorrent/include/libtorrent/asio/detail/handler_queue.hpp rename to libtorrent/include/asio/detail/handler_queue.hpp index 63c78a7d0..989f976b2 100644 --- a/libtorrent/include/libtorrent/asio/detail/handler_queue.hpp +++ b/libtorrent/include/asio/detail/handler_queue.hpp @@ -198,6 +198,16 @@ private: this_type* h(static_cast(base)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(h->handler_, h); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(h->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } private: diff --git a/libtorrent/include/libtorrent/asio/detail/hash_map.hpp b/libtorrent/include/asio/detail/hash_map.hpp similarity index 84% rename from libtorrent/include/libtorrent/asio/detail/hash_map.hpp rename to libtorrent/include/asio/detail/hash_map.hpp index 8560e5879..bbbb406f8 100644 --- a/libtorrent/include/libtorrent/asio/detail/hash_map.hpp +++ b/libtorrent/include/asio/detail/hash_map.hpp @@ -43,6 +43,7 @@ inline std::size_t calculate_hash_value(SOCKET s) } #endif // defined(_WIN64) +// Note: assumes K and V are POD types. template class hash_map : private noncopyable @@ -139,7 +140,7 @@ public: if (it == values_.end()) { buckets_[bucket].first = buckets_[bucket].last = - values_.insert(values_.end(), v); + values_insert(values_.end(), v); return std::pair(buckets_[bucket].last, true); } iterator end = buckets_[bucket].last; @@ -150,7 +151,7 @@ public: return std::pair(it, false); ++it; } - buckets_[bucket].last = values_.insert(end, v); + buckets_[bucket].last = values_insert(end, v); return std::pair(buckets_[bucket].last, true); } @@ -169,7 +170,7 @@ public: else if (is_last) --buckets_[bucket].last; - values_.erase(it); + values_erase(it); } // Remove all entries from the map. @@ -184,9 +185,36 @@ public: } private: + // Insert an element into the values list by splicing from the spares list, + // if a spare is available, and otherwise by inserting a new element. + iterator values_insert(iterator it, const value_type& v) + { + if (spares_.empty()) + { + return values_.insert(it, v); + } + else + { + spares_.front() = v; + values_.splice(it, spares_, spares_.begin()); + return --it; + } + } + + // Erase an element from the values list by splicing it to the spares list. + void values_erase(iterator it) + { + *it = value_type(); + spares_.splice(spares_.begin(), values_, it); + } + // The list of all values in the hash map. std::list values_; + // The list of spare nodes waiting to be recycled. Assumes that POD types only + // are stored in the hash map. + std::list spares_; + // The type for a bucket in the hash table. struct bucket_type { diff --git a/libtorrent/include/asio/detail/indirect_handler_queue.hpp b/libtorrent/include/asio/detail/indirect_handler_queue.hpp new file mode 100644 index 000000000..d08a7df4d --- /dev/null +++ b/libtorrent/include/asio/detail/indirect_handler_queue.hpp @@ -0,0 +1,291 @@ +// +// indirect_handler_queue.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP +#define ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/noncopyable.hpp" + +#if defined(_MSC_VER) && (_MSC_VER >= 1310) +extern "C" void _ReadWriteBarrier(); +# pragma intrinsic(_ReadWriteBarrier) +#endif // defined(_MSC_VER) && (_MSC_VER >= 1310) + +namespace asio { +namespace detail { + +class indirect_handler_queue + : private noncopyable +{ +public: + class handler; + + // Element for a node in the queue. + class node + { + public: + node() + : version_(0), + handler_(0), + next_(0) + { + } + + private: + friend class indirect_handler_queue; + unsigned long version_; + handler* handler_; + node* next_; + }; + + // Base class for handlers in the queue. + class handler + : private noncopyable + { + public: + void invoke() + { + invoke_func_(this); + } + + void destroy() + { + destroy_func_(this); + } + + protected: + typedef void (*invoke_func_type)(handler*); + typedef void (*destroy_func_type)(handler*); + + handler(invoke_func_type invoke_func, + destroy_func_type destroy_func) + : node_(new node), + invoke_func_(invoke_func), + destroy_func_(destroy_func) + { + } + + ~handler() + { + if (node_) + delete node_; + } + + private: + friend class indirect_handler_queue; + node* node_; + invoke_func_type invoke_func_; + destroy_func_type destroy_func_; + }; + + // Smart point to manager handler lifetimes. + class scoped_ptr + : private noncopyable + { + public: + explicit scoped_ptr(handler* h) + : handler_(h) + { + } + + ~scoped_ptr() + { + if (handler_) + handler_->destroy(); + } + + handler* get() const + { + return handler_; + } + + handler* release() + { + handler* tmp = handler_; + handler_ = 0; + return tmp; + } + + private: + handler* handler_; + }; + + // Constructor. + indirect_handler_queue() + : front_(new node), + back_(front_), + next_version_(1) + { + } + + // Destructor. + ~indirect_handler_queue() + { + while (front_) + { + node* tmp = front_; + front_ = front_->next_; + delete tmp; + } + } + + // Wrap a handler to be pushed into the queue. + template + static handler* wrap(Handler h) + { + // Allocate and construct an object to wrap the handler. + typedef handler_wrapper value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(h); + handler_ptr ptr(raw_ptr, h); + return ptr.release(); + } + + // Determine whether the queue has something ready to pop. + bool poppable() + { + return front_->next_ != 0; + } + + // The version number at the front of the queue. + unsigned long front_version() + { + return front_->version_; + } + + // The version number at the back of the queue. + unsigned long back_version() + { + return back_->version_; + } + + // Pop a handler from the front of the queue. + handler* pop() + { + node* n = front_; + node* new_front = n->next_; + if (new_front) + { + handler* h = new_front->handler_; + h->node_ = n; + new_front->handler_ = 0; + front_ = new_front; + return h; + } + return 0; + } + + // Push a handler on to the back of the queue. + void push(handler* h) + { + node* n = h->node_; + h->node_ = 0; + n->version_ = next_version_; + next_version_ += 2; + n->handler_ = h; + n->next_ = 0; + memory_barrier(); + back_->next_ = n; + back_ = n; + } + +private: + // Template wrapper for handlers. + template + class handler_wrapper + : public handler + { + public: + handler_wrapper(Handler h) + : handler( + &handler_wrapper::do_call, + &handler_wrapper::do_destroy), + handler_(h) + { + } + + static void do_call(handler* base) + { + // Take ownership of the handler object. + typedef handler_wrapper this_type; + this_type* h(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(h->handler_, h); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(h->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Make the upcall. + asio_handler_invoke_helpers::invoke(handler, &handler); + } + + static void do_destroy(handler* base) + { + // Take ownership of the handler object. + typedef handler_wrapper this_type; + this_type* h(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(h->handler_, h); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(h->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + private: + Handler handler_; + }; + + // Helper function to create a memory barrier. + static void memory_barrier() + { +#if defined(_GLIBCXX_WRITE_MEM_BARRIER) + _GLIBCXX_WRITE_MEM_BARRIER; +#elif defined(_MSC_VER) && (_MSC_VER >= 1310) + _ReadWriteBarrier(); +#else +# error memory barrier required +#endif + } + + // The front of the queue. + node* front_; + + // The back of the queue. + node* back_; + + // The next version counter to be assigned to a node. + unsigned long next_version_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/io_control.hpp b/libtorrent/include/asio/detail/io_control.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/io_control.hpp rename to libtorrent/include/asio/detail/io_control.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/kqueue_reactor.hpp b/libtorrent/include/asio/detail/kqueue_reactor.hpp similarity index 78% rename from libtorrent/include/libtorrent/asio/detail/kqueue_reactor.hpp rename to libtorrent/include/asio/detail/kqueue_reactor.hpp index 20163181b..1d0d21aba 100644 --- a/libtorrent/include/libtorrent/asio/detail/kqueue_reactor.hpp +++ b/libtorrent/include/asio/detail/kqueue_reactor.hpp @@ -60,6 +60,13 @@ class kqueue_reactor : public asio::detail::service_base > { public: + // Per-descriptor data. + struct per_descriptor_data + { + bool allow_speculative_read; + bool allow_speculative_write; + }; + // Constructor. kqueue_reactor(asio::io_service& io_service) : asio::detail::service_base< @@ -126,24 +133,58 @@ public: // Register a socket with the reactor. Returns 0 on success, system error // code on failure. - int register_descriptor(socket_type) + int register_descriptor(socket_type, per_descriptor_data& descriptor_data) { + descriptor_data.allow_speculative_read = true; + descriptor_data.allow_speculative_write = true; + return 0; } // Start a new read operation. The handler object will be invoked when the // given descriptor is ready to be read, or an error has occurred. template - void start_read_op(socket_type descriptor, Handler handler) + void start_read_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler, + bool allow_speculative_read = true) { + if (allow_speculative_read && descriptor_data.allow_speculative_read) + { + asio::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative read in this function. + allow_speculative_read = false; + } + asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!read_op_queue_.has_operation(descriptor)) - if (handler(asio::error_code())) + if (!allow_speculative_read) + need_kqueue_wait_ = true; + else if (!read_op_queue_.has_operation(descriptor)) + { + // Speculative reads are ok as there are no queued read operations. + descriptor_data.allow_speculative_read = true; + + asio::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); return; + } + } + + // Speculative reads are not ok as there will be queued read operations. + descriptor_data.allow_speculative_read = false; if (read_op_queue_.enqueue_operation(descriptor, handler)) { @@ -153,7 +194,7 @@ public: { asio::error_code ec(errno, asio::error::get_system_category()); - read_op_queue_.dispatch_all_operations(descriptor, ec); + read_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -161,16 +202,47 @@ public: // Start a new write operation. The handler object will be invoked when the // given descriptor is ready to be written, or an error has occurred. template - void start_write_op(socket_type descriptor, Handler handler) + void start_write_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler, + bool allow_speculative_write = true) { + if (allow_speculative_write && descriptor_data.allow_speculative_write) + { + asio::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative write in this function. + allow_speculative_write = false; + } + asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!write_op_queue_.has_operation(descriptor)) - if (handler(asio::error_code())) + if (!allow_speculative_write) + need_kqueue_wait_ = true; + else if (!write_op_queue_.has_operation(descriptor)) + { + // Speculative writes are ok as there are no queued write operations. + descriptor_data.allow_speculative_write = true; + + asio::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); return; + } + } + + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; if (write_op_queue_.enqueue_operation(descriptor, handler)) { @@ -180,7 +252,7 @@ public: { asio::error_code ec(errno, asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -188,7 +260,8 @@ public: // Start a new exception operation. The handler object will be invoked when // the given descriptor has exception information, or an error has occurred. template - void start_except_op(socket_type descriptor, Handler handler) + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { asio::detail::mutex::scoped_lock lock(mutex_); @@ -206,22 +279,25 @@ public: { asio::error_code ec(errno, asio::error::get_system_category()); - except_op_queue_.dispatch_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); } } } - // Start new write and exception operations. The handler object will be - // invoked when the given descriptor is ready for writing or has exception - // information available, or an error has occurred. + // Start a new write operation. The handler object will be invoked when the + // given descriptor is ready to be written, or an error has occurred. template - void start_write_and_except_ops(socket_type descriptor, Handler handler) + void start_connect_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler) { asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; + if (write_op_queue_.enqueue_operation(descriptor, handler)) { struct kevent event; @@ -230,23 +306,7 @@ public: { asio::error_code ec(errno, asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - - if (except_op_queue_.enqueue_operation(descriptor, handler)) - { - struct kevent event; - if (read_op_queue_.has_operation(descriptor)) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code ec(errno, - asio::error::get_system_category()); - except_op_queue_.dispatch_all_operations(descriptor, ec); - write_op_queue_.dispatch_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -254,25 +314,15 @@ public: // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. - void cancel_ops(socket_type descriptor) + void cancel_ops(socket_type descriptor, per_descriptor_data&) { asio::detail::mutex::scoped_lock lock(mutex_); cancel_ops_unlocked(descriptor); } - // Enqueue cancellation of all operations associated with the given - // descriptor. The handlers associated with the descriptor will be invoked - // with the operation_aborted error. This function does not acquire the - // kqueue_reactor's mutex, and so should only be used from within a reactor - // handler. - void enqueue_cancel_ops_unlocked(socket_type descriptor) - { - pending_cancellations_.push_back(descriptor); - } - // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. - void close_descriptor(socket_type descriptor) + void close_descriptor(socket_type descriptor, per_descriptor_data&) { asio::detail::mutex::scoped_lock lock(mutex_); @@ -343,16 +393,16 @@ private: // Dispatch any operation cancellations that were made while the select // loop was not running. - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) timer_queues_[i]->dispatch_cancellations(); // Check if the thread is supposed to stop. if (stop_thread_) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -361,7 +411,7 @@ private: if (!block && read_op_queue_.empty() && write_op_queue_.empty() && except_op_queue_.empty() && all_timer_queues_are_empty()) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -381,7 +431,7 @@ private: lock.lock(); wait_in_progress_ = false; - // Block signals while dispatching operations. + // Block signals while performing operations. asio::detail::signal_blocker sb; // Dispatch the waiting events. @@ -401,22 +451,22 @@ private: { asio::error_code error( events[i].data, asio::error::get_system_category()); - except_op_queue_.dispatch_all_operations(descriptor, error); - read_op_queue_.dispatch_all_operations(descriptor, error); + except_op_queue_.perform_all_operations(descriptor, error); + read_op_queue_.perform_all_operations(descriptor, error); } else if (events[i].flags & EV_OOBAND) { asio::error_code error; - more_except = except_op_queue_.dispatch_operation(descriptor, error); + more_except = except_op_queue_.perform_operation(descriptor, error); if (events[i].data > 0) - more_reads = read_op_queue_.dispatch_operation(descriptor, error); + more_reads = read_op_queue_.perform_operation(descriptor, error); else more_reads = read_op_queue_.has_operation(descriptor); } else { asio::error_code error; - more_reads = read_op_queue_.dispatch_operation(descriptor, error); + more_reads = read_op_queue_.perform_operation(descriptor, error); more_except = except_op_queue_.has_operation(descriptor); } @@ -432,8 +482,8 @@ private: { asio::error_code error(errno, asio::error::get_system_category()); - except_op_queue_.dispatch_all_operations(descriptor, error); - read_op_queue_.dispatch_all_operations(descriptor, error); + except_op_queue_.perform_all_operations(descriptor, error); + read_op_queue_.perform_all_operations(descriptor, error); } } else if (events[i].filter == EVFILT_WRITE) @@ -444,12 +494,12 @@ private: { asio::error_code error( events[i].data, asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, error); + write_op_queue_.perform_all_operations(descriptor, error); } else { asio::error_code error; - more_writes = write_op_queue_.dispatch_operation(descriptor, error); + more_writes = write_op_queue_.perform_operation(descriptor, error); } // Update the descriptor in the kqueue. @@ -462,14 +512,14 @@ private: { asio::error_code error(errno, asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, error); + write_op_queue_.perform_all_operations(descriptor, error); } } } - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) { timer_queues_[i]->dispatch_timers(); @@ -485,7 +535,7 @@ private: need_kqueue_wait_ = !read_op_queue_.empty() || !write_op_queue_.empty() || !except_op_queue_.empty(); - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); } // Run the select loop in the thread. @@ -586,16 +636,16 @@ private: // destructors may make calls back into this reactor. We make a copy of the // vector of timer queues since the original may be modified while the lock // is not held. - void cleanup_operations_and_timers( + void complete_operations_and_timers( asio::detail::mutex::scoped_lock& lock) { timer_queues_for_cleanup_ = timer_queues_; lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->cleanup_timers(); + timer_queues_for_cleanup_[i]->complete_timers(); } // Mutex to protect access to internal data. diff --git a/libtorrent/include/libtorrent/asio/detail/kqueue_reactor_fwd.hpp b/libtorrent/include/asio/detail/kqueue_reactor_fwd.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/kqueue_reactor_fwd.hpp rename to libtorrent/include/asio/detail/kqueue_reactor_fwd.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/local_free_on_block_exit.hpp b/libtorrent/include/asio/detail/local_free_on_block_exit.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/local_free_on_block_exit.hpp rename to libtorrent/include/asio/detail/local_free_on_block_exit.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/mutex.hpp b/libtorrent/include/asio/detail/mutex.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/mutex.hpp rename to libtorrent/include/asio/detail/mutex.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/noncopyable.hpp b/libtorrent/include/asio/detail/noncopyable.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/noncopyable.hpp rename to libtorrent/include/asio/detail/noncopyable.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/null_event.hpp b/libtorrent/include/asio/detail/null_event.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/null_event.hpp rename to libtorrent/include/asio/detail/null_event.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/null_mutex.hpp b/libtorrent/include/asio/detail/null_mutex.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/null_mutex.hpp rename to libtorrent/include/asio/detail/null_mutex.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/null_signal_blocker.hpp b/libtorrent/include/asio/detail/null_signal_blocker.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/null_signal_blocker.hpp rename to libtorrent/include/asio/detail/null_signal_blocker.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/null_thread.hpp b/libtorrent/include/asio/detail/null_thread.hpp similarity index 92% rename from libtorrent/include/libtorrent/asio/detail/null_thread.hpp rename to libtorrent/include/asio/detail/null_thread.hpp index f91ca53e0..f08b7b378 100644 --- a/libtorrent/include/libtorrent/asio/detail/null_thread.hpp +++ b/libtorrent/include/asio/detail/null_thread.hpp @@ -38,9 +38,12 @@ class null_thread : private noncopyable { public: + // The purpose of the thread. + enum purpose { internal, external }; + // Constructor. template - null_thread(Function f) + null_thread(Function f, purpose = internal) { asio::system_error e( asio::error::operation_not_supported, "thread"); diff --git a/libtorrent/include/libtorrent/asio/detail/null_tss_ptr.hpp b/libtorrent/include/asio/detail/null_tss_ptr.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/null_tss_ptr.hpp rename to libtorrent/include/asio/detail/null_tss_ptr.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/old_win_sdk_compat.hpp b/libtorrent/include/asio/detail/old_win_sdk_compat.hpp similarity index 98% rename from libtorrent/include/libtorrent/asio/detail/old_win_sdk_compat.hpp rename to libtorrent/include/asio/detail/old_win_sdk_compat.hpp index a935677e1..b73a09012 100644 --- a/libtorrent/include/libtorrent/asio/detail/old_win_sdk_compat.hpp +++ b/libtorrent/include/asio/detail/old_win_sdk_compat.hpp @@ -328,6 +328,11 @@ inline int IN6_IS_ADDR_MC_GLOBAL(const in6_addr_emulation* a) # define IPV6_V6ONLY 27 #endif +// Some SDKs (e.g. Windows CE) don't define IPPROTO_ICMPV6. +#if !defined(IPPROTO_ICMPV6) +# define IPPROTO_ICMPV6 58 +#endif + #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #include "asio/detail/pop_options.hpp" diff --git a/libtorrent/include/libtorrent/asio/detail/pipe_select_interrupter.hpp b/libtorrent/include/asio/detail/pipe_select_interrupter.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/pipe_select_interrupter.hpp rename to libtorrent/include/asio/detail/pipe_select_interrupter.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/pop_options.hpp b/libtorrent/include/asio/detail/pop_options.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/pop_options.hpp rename to libtorrent/include/asio/detail/pop_options.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/posix_event.hpp b/libtorrent/include/asio/detail/posix_event.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/posix_event.hpp rename to libtorrent/include/asio/detail/posix_event.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp b/libtorrent/include/asio/detail/posix_fd_set_adapter.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp rename to libtorrent/include/asio/detail/posix_fd_set_adapter.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/posix_mutex.hpp b/libtorrent/include/asio/detail/posix_mutex.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/posix_mutex.hpp rename to libtorrent/include/asio/detail/posix_mutex.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/posix_signal_blocker.hpp b/libtorrent/include/asio/detail/posix_signal_blocker.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/posix_signal_blocker.hpp rename to libtorrent/include/asio/detail/posix_signal_blocker.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/posix_thread.hpp b/libtorrent/include/asio/detail/posix_thread.hpp similarity index 95% rename from libtorrent/include/libtorrent/asio/detail/posix_thread.hpp rename to libtorrent/include/asio/detail/posix_thread.hpp index 892ffe076..fe5f82905 100644 --- a/libtorrent/include/libtorrent/asio/detail/posix_thread.hpp +++ b/libtorrent/include/asio/detail/posix_thread.hpp @@ -42,9 +42,12 @@ class posix_thread : private noncopyable { public: + // The purpose of the thread. + enum purpose { internal, external }; + // Constructor. template - posix_thread(Function f) + posix_thread(Function f, purpose = internal) : joined_(false) { std::auto_ptr arg(new func(f)); diff --git a/libtorrent/include/libtorrent/asio/detail/posix_tss_ptr.hpp b/libtorrent/include/asio/detail/posix_tss_ptr.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/posix_tss_ptr.hpp rename to libtorrent/include/asio/detail/posix_tss_ptr.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/push_options.hpp b/libtorrent/include/asio/detail/push_options.hpp similarity index 97% rename from libtorrent/include/libtorrent/asio/detail/push_options.hpp rename to libtorrent/include/asio/detail/push_options.hpp index 4e0524dc5..47524b255 100644 --- a/libtorrent/include/libtorrent/asio/detail/push_options.hpp +++ b/libtorrent/include/asio/detail/push_options.hpp @@ -87,8 +87,10 @@ # pragma warning (disable:4103) # pragma warning (push) +# pragma warning (disable:4127) # pragma warning (disable:4244) # pragma warning (disable:4355) +# pragma warning (disable:4512) # pragma warning (disable:4675) # if defined(_M_IX86) && defined(_Wp64) // The /Wp64 option is broken. If you want to check 64 bit portability, use a diff --git a/libtorrent/include/asio/detail/reactive_descriptor_service.hpp b/libtorrent/include/asio/detail/reactive_descriptor_service.hpp new file mode 100644 index 000000000..12a0c36b4 --- /dev/null +++ b/libtorrent/include/asio/detail/reactive_descriptor_service.hpp @@ -0,0 +1,709 @@ +// +// reactive_descriptor_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP +#define ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/buffer.hpp" +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/handler_base_from_member.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/detail/service_base.hpp" +#include "asio/detail/descriptor_ops.hpp" + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +namespace asio { +namespace detail { + +template +class reactive_descriptor_service + : public asio::detail::service_base< + reactive_descriptor_service > +{ +public: + // The native type of a descriptor. + typedef int native_type; + + // The implementation type of the descriptor. + class implementation_type + : private asio::detail::noncopyable + { + public: + // Default constructor. + implementation_type() + : descriptor_(-1), + flags_(0) + { + } + + private: + // Only this service will have access to the internal values. + friend class reactive_descriptor_service; + + // The native descriptor representation. + int descriptor_; + + enum + { + user_set_non_blocking = 1, // The user wants a non-blocking descriptor. + internal_non_blocking = 2 // The descriptor has been set non-blocking. + }; + + // Flags indicating the current state of the descriptor. + unsigned char flags_; + + // Per-descriptor data used by the reactor. + typename Reactor::per_descriptor_data reactor_data_; + }; + + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; + + // Constructor. + reactive_descriptor_service(asio::io_service& io_service) + : asio::detail::service_base< + reactive_descriptor_service >(io_service), + reactor_(asio::use_service(io_service)) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new descriptor implementation. + void construct(implementation_type& impl) + { + impl.descriptor_ = -1; + impl.flags_ = 0; + } + + // Destroy a descriptor implementation. + void destroy(implementation_type& impl) + { + if (impl.descriptor_ != -1) + { + reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_); + + if (impl.flags_ & implementation_type::internal_non_blocking) + { + ioctl_arg_type non_blocking = 0; + asio::error_code ignored_ec; + descriptor_ops::ioctl(impl.descriptor_, + FIONBIO, &non_blocking, ignored_ec); + impl.flags_ &= ~implementation_type::internal_non_blocking; + } + + asio::error_code ignored_ec; + descriptor_ops::close(impl.descriptor_, ignored_ec); + + impl.descriptor_ = -1; + } + } + + // Assign a native descriptor to a descriptor implementation. + asio::error_code assign(implementation_type& impl, + const native_type& native_descriptor, asio::error_code& ec) + { + if (is_open(impl)) + { + ec = asio::error::already_open; + return ec; + } + + if (int err = reactor_.register_descriptor( + native_descriptor, impl.reactor_data_)) + { + ec = asio::error_code(err, + asio::error::get_system_category()); + return ec; + } + + impl.descriptor_ = native_descriptor; + impl.flags_ = 0; + ec = asio::error_code(); + return ec; + } + + // Determine whether the descriptor is open. + bool is_open(const implementation_type& impl) const + { + return impl.descriptor_ != -1; + } + + // Destroy a descriptor implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + if (is_open(impl)) + { + reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_); + + if (impl.flags_ & implementation_type::internal_non_blocking) + { + ioctl_arg_type non_blocking = 0; + asio::error_code ignored_ec; + descriptor_ops::ioctl(impl.descriptor_, + FIONBIO, &non_blocking, ignored_ec); + impl.flags_ &= ~implementation_type::internal_non_blocking; + } + + if (descriptor_ops::close(impl.descriptor_, ec) == -1) + return ec; + + impl.descriptor_ = -1; + } + + ec = asio::error_code(); + return ec; + } + + // Get the native descriptor representation. + native_type native(const implementation_type& impl) const + { + return impl.descriptor_; + } + + // Cancel all operations associated with the descriptor. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return ec; + } + + reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_); + ec = asio::error_code(); + return ec; + } + + // Perform an IO control command on the descriptor. + template + asio::error_code io_control(implementation_type& impl, + IO_Control_Command& command, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return ec; + } + + if (command.name() == static_cast(FIONBIO)) + { + if (command.get()) + impl.flags_ |= implementation_type::user_set_non_blocking; + else + impl.flags_ &= ~implementation_type::user_set_non_blocking; + ec = asio::error_code(); + } + else + { + descriptor_ops::ioctl(impl.descriptor_, command.name(), + static_cast(command.data()), ec); + } + return ec; + } + + // Write some data to the descriptor. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + asio::const_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + asio::buffer_cast(buffer), + asio::buffer_size(buffer)); + total_buffer_size += asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + ec = asio::error_code(); + return 0; + } + + // Make descriptor non-blocking if user wants non-blocking. + if (impl.flags_ & implementation_type::user_set_non_blocking) + { + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + if (descriptor_ops::ioctl(impl.descriptor_, + FIONBIO, &non_blocking, ec)) + return 0; + impl.flags_ |= implementation_type::internal_non_blocking; + } + } + + // Send the data. + for (;;) + { + // Try to complete the operation without blocking. + int bytes_sent = descriptor_ops::gather_write( + impl.descriptor_, bufs, i, ec); + + // Check if operation succeeded. + if (bytes_sent >= 0) + return bytes_sent; + + // Operation failed. + if ((impl.flags_ & implementation_type::user_set_non_blocking) + || (ec != asio::error::would_block + && ec != asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_write(impl.descriptor_, ec) < 0) + return 0; + } + } + + // Wait until data can be written without blocking. + size_t write_some(implementation_type& impl, + const null_buffers&, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Wait for descriptor to become ready. + descriptor_ops::poll_write(impl.descriptor_, ec); + + return 0; + } + + template + class write_operation : + public handler_base_from_member + { + public: + write_operation(int descriptor, asio::io_service& io_service, + const ConstBufferSequence& buffers, Handler handler) + : handler_base_from_member(handler), + descriptor_(descriptor), + io_service_(io_service), + work_(io_service), + buffers_(buffers) + { + } + + bool perform(asio::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether the operation was successful. + if (ec) + { + bytes_transferred = 0; + return true; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers_.begin(); + typename ConstBufferSequence::const_iterator end = buffers_.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + asio::const_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + asio::buffer_cast(buffer), + asio::buffer_size(buffer)); + } + + // Write the data. + int bytes = descriptor_ops::gather_write(descriptor_, bufs, i, ec); + + // Check if we need to run the operation again. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + return false; + + bytes_transferred = (bytes < 0 ? 0 : bytes); + return true; + } + + void complete(const asio::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + + private: + int descriptor_; + asio::io_service& io_service_; + asio::io_service::work work_; + ConstBufferSequence buffers_; + }; + + // Start an asynchronous write. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else + { + // Determine total size of buffers. + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + asio::const_buffer buffer(*iter); + total_buffer_size += asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + this->get_io_service().post(bind_handler(handler, + asio::error_code(), 0)); + return; + } + + // Make descriptor non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + asio::error_code ec; + if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec, 0)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + reactor_.start_write_op(impl.descriptor_, impl.reactor_data_, + write_operation( + impl.descriptor_, this->get_io_service(), buffers, handler)); + } + } + + template + class null_buffers_operation : + public handler_base_from_member + { + public: + null_buffers_operation(asio::io_service& io_service, Handler handler) + : handler_base_from_member(handler), + work_(io_service) + { + } + + bool perform(asio::error_code&, + std::size_t& bytes_transferred) + { + bytes_transferred = 0; + return true; + } + + void complete(const asio::error_code& ec, + std::size_t bytes_transferred) + { + work_.get_io_service().post(bind_handler( + this->handler_, ec, bytes_transferred)); + } + + private: + asio::io_service::work work_; + }; + + // Start an asynchronous wait until data can be written without blocking. + template + void async_write_some(implementation_type& impl, + const null_buffers&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_write_op(impl.descriptor_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + + // Read some data from the stream. Returns the number of bytes read. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + asio::mutable_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + asio::buffer_cast(buffer), + asio::buffer_size(buffer)); + total_buffer_size += asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + ec = asio::error_code(); + return 0; + } + + // Make descriptor non-blocking if user wants non-blocking. + if (impl.flags_ & implementation_type::user_set_non_blocking) + { + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) + return 0; + impl.flags_ |= implementation_type::internal_non_blocking; + } + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + int bytes_read = descriptor_ops::scatter_read( + impl.descriptor_, bufs, i, ec); + + // Check if operation succeeded. + if (bytes_read > 0) + return bytes_read; + + // Check for EOF. + if (bytes_read == 0) + { + ec = asio::error::eof; + return 0; + } + + // Operation failed. + if ((impl.flags_ & implementation_type::user_set_non_blocking) + || (ec != asio::error::would_block + && ec != asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_read(impl.descriptor_, ec) < 0) + return 0; + } + } + + // Wait until data can be read without blocking. + size_t read_some(implementation_type& impl, + const null_buffers&, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Wait for descriptor to become ready. + descriptor_ops::poll_read(impl.descriptor_, ec); + + return 0; + } + + template + class read_operation : + public handler_base_from_member + { + public: + read_operation(int descriptor, asio::io_service& io_service, + const MutableBufferSequence& buffers, Handler handler) + : handler_base_from_member(handler), + descriptor_(descriptor), + io_service_(io_service), + work_(io_service), + buffers_(buffers) + { + } + + bool perform(asio::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether the operation was successful. + if (ec) + { + bytes_transferred = 0; + return true; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers_.begin(); + typename MutableBufferSequence::const_iterator end = buffers_.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + asio::mutable_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + asio::buffer_cast(buffer), + asio::buffer_size(buffer)); + } + + // Read some data. + int bytes = descriptor_ops::scatter_read(descriptor_, bufs, i, ec); + if (bytes == 0) + ec = asio::error::eof; + + // Check if we need to run the operation again. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + return false; + + bytes_transferred = (bytes < 0 ? 0 : bytes); + return true; + } + + void complete(const asio::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + + private: + int descriptor_; + asio::io_service& io_service_; + asio::io_service::work work_; + MutableBufferSequence buffers_; + }; + + // Start an asynchronous read. The buffer for the data being read must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else + { + // Determine total size of buffers. + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + asio::mutable_buffer buffer(*iter); + total_buffer_size += asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + this->get_io_service().post(bind_handler(handler, + asio::error_code(), 0)); + return; + } + + // Make descriptor non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + asio::error_code ec; + if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec, 0)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + reactor_.start_read_op(impl.descriptor_, impl.reactor_data_, + read_operation( + impl.descriptor_, this->get_io_service(), buffers, handler)); + } + } + + // Wait until data can be read without blocking. + template + void async_read_some(implementation_type& impl, + const null_buffers&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_read_op(impl.descriptor_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + +private: + // The selector that performs event demultiplexing for the service. + Reactor& reactor_; +}; + +} // namespace detail +} // namespace asio + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/reactive_serial_port_service.hpp b/libtorrent/include/asio/detail/reactive_serial_port_service.hpp new file mode 100644 index 000000000..5db94a2dd --- /dev/null +++ b/libtorrent/include/asio/detail/reactive_serial_port_service.hpp @@ -0,0 +1,267 @@ +// +// reactive_serial_port_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP +#define ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include "asio/detail/push_options.hpp" +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/descriptor_ops.hpp" +#include "asio/detail/reactive_descriptor_service.hpp" + +namespace asio { +namespace detail { + +// Extend reactive_descriptor_service to provide serial port support. +template +class reactive_serial_port_service + : public asio::detail::service_base< + reactive_serial_port_service > +{ +public: + // The native type of a stream handle. + typedef typename reactive_descriptor_service::native_type + native_type; + + // The implementation type of the stream handle. + typedef typename reactive_descriptor_service::implementation_type + implementation_type; + + reactive_serial_port_service(asio::io_service& io_service) + : asio::detail::service_base< + reactive_serial_port_service>(io_service), + descriptor_service_(asio::use_service< + reactive_descriptor_service >(io_service)) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new handle implementation. + void construct(implementation_type& impl) + { + descriptor_service_.construct(impl); + } + + // Destroy a handle implementation. + void destroy(implementation_type& impl) + { + descriptor_service_.destroy(impl); + } + + // Open the serial port using the specified device name. + asio::error_code open(implementation_type& impl, + const std::string& device, asio::error_code& ec) + { + if (is_open(impl)) + { + ec = asio::error::already_open; + return ec; + } + + int fd = descriptor_ops::open(device.c_str(), + O_RDWR | O_NONBLOCK | O_NOCTTY, ec); + if (fd < 0) + return ec; + + int s = descriptor_ops::fcntl(fd, F_GETFL, ec); + if (s >= 0) + s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec); + if (s < 0) + { + asio::error_code ignored_ec; + descriptor_ops::close(fd, ignored_ec); + return ec; + } + + // Set up default serial port options. + termios ios; + descriptor_ops::clear_error(ec); + s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec); + if (s >= 0) + { +#if defined(_BSD_SOURCE) + ::cfmakeraw(&ios); +#else + ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK + | ISTRIP | INLCR | IGNCR | ICRNL | IXON); + ios.c_oflag &= ~OPOST; + ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + ios.c_cflag &= ~(CSIZE | PARENB); + ios.c_cflag |= CS8; +#endif + ios.c_iflag |= IGNPAR; + descriptor_ops::clear_error(ec); + s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec); + } + if (s < 0) + { + asio::error_code ignored_ec; + descriptor_ops::close(fd, ignored_ec); + return ec; + } + + // We're done. Take ownership of the serial port descriptor. + if (descriptor_service_.assign(impl, fd, ec)) + { + asio::error_code ignored_ec; + descriptor_ops::close(fd, ignored_ec); + } + + return ec; + } + + // Assign a native handle to a handle implementation. + asio::error_code assign(implementation_type& impl, + const native_type& native_descriptor, asio::error_code& ec) + { + return descriptor_service_.assign(impl, native_descriptor, ec); + } + + // Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return descriptor_service_.is_open(impl); + } + + // Destroy a handle implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + return descriptor_service_.close(impl, ec); + } + + // Get the native handle representation. + native_type native(implementation_type& impl) + { + return descriptor_service_.native(impl); + } + + // Cancel all operations associated with the handle. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + return descriptor_service_.cancel(impl, ec); + } + + // Set an option on the serial port. + template + asio::error_code set_option(implementation_type& impl, + const SettableSerialPortOption& option, asio::error_code& ec) + { + termios ios; + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcgetattr( + descriptor_service_.native(impl), &ios), ec); + if (ec) + return ec; + + if (option.store(ios, ec)) + return ec; + + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcsetattr( + descriptor_service_.native(impl), TCSANOW, &ios), ec); + return ec; + } + + // Get an option from the serial port. + template + asio::error_code get_option(const implementation_type& impl, + GettableSerialPortOption& option, asio::error_code& ec) const + { + termios ios; + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcgetattr( + descriptor_service_.native(impl), &ios), ec); + if (ec) + return ec; + + return option.load(ios, ec); + } + + // Send a break sequence to the serial port. + asio::error_code send_break(implementation_type& impl, + asio::error_code& ec) + { + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcsendbreak( + descriptor_service_.native(impl), 0), ec); + return ec; + } + + // Write the given data. Returns the number of bytes sent. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return descriptor_service_.write_some(impl, buffers, ec); + } + + // Start an asynchronous write. The data being written must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + descriptor_service_.async_write_some(impl, buffers, handler); + } + + // Read some data. Returns the number of bytes received. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return descriptor_service_.read_some(impl, buffers, ec); + } + + // Start an asynchronous read. The buffer for the data being received must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + descriptor_service_.async_read_some(impl, buffers, handler); + } + +private: + // The handle service used for initiating asynchronous operations. + reactive_descriptor_service& descriptor_service_; +}; + +} // namespace detail +} // namespace asio + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/reactive_socket_service.hpp b/libtorrent/include/asio/detail/reactive_socket_service.hpp similarity index 79% rename from libtorrent/include/libtorrent/asio/detail/reactive_socket_service.hpp rename to libtorrent/include/asio/detail/reactive_socket_service.hpp index 0ecabaa0e..c7aedf88e 100644 --- a/libtorrent/include/libtorrent/asio/detail/reactive_socket_service.hpp +++ b/libtorrent/include/asio/detail/reactive_socket_service.hpp @@ -26,6 +26,7 @@ #include "asio/io_service.hpp" #include "asio/socket_base.hpp" #include "asio/detail/bind_handler.hpp" +#include "asio/detail/handler_base_from_member.hpp" #include "asio/detail/noncopyable.hpp" #include "asio/detail/service_base.hpp" #include "asio/detail/socket_holder.hpp" @@ -83,6 +84,9 @@ public: // The protocol associated with the socket. protocol_type protocol_; + + // Per-descriptor data used by the reactor. + typename Reactor::per_descriptor_data reactor_data_; }; // The maximum number of buffers to support in a single operation. @@ -113,7 +117,7 @@ public: { if (impl.socket_ != invalid_socket) { - reactor_.close_descriptor(impl.socket_); + reactor_.close_descriptor(impl.socket_, impl.reactor_data_); if (impl.flags_ & implementation_type::internal_non_blocking) { @@ -155,7 +159,7 @@ public: if (sock.get() == invalid_socket) return ec; - if (int err = reactor_.register_descriptor(sock.get())) + if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) { ec = asio::error_code(err, asio::error::get_system_category()); @@ -180,7 +184,8 @@ public: return ec; } - if (int err = reactor_.register_descriptor(native_socket)) + if (int err = reactor_.register_descriptor( + native_socket, impl.reactor_data_)) { ec = asio::error_code(err, asio::error::get_system_category()); @@ -206,7 +211,7 @@ public: { if (is_open(impl)) { - reactor_.close_descriptor(impl.socket_); + reactor_.close_descriptor(impl.socket_, impl.reactor_data_); if (impl.flags_ & implementation_type::internal_non_blocking) { @@ -242,7 +247,7 @@ public: return ec; } - reactor_.cancel_ops(impl.socket_); + reactor_.cancel_ops(impl.socket_, impl.reactor_data_); ec = asio::error_code(); return ec; } @@ -558,28 +563,46 @@ public: } } + // Wait until data can be sent without blocking. + size_t send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + template - class send_handler + class send_operation : + public handler_base_from_member { public: - send_handler(socket_type socket, asio::io_service& io_service, + send_operation(socket_type socket, asio::io_service& io_service, const ConstBufferSequence& buffers, socket_base::message_flags flags, Handler handler) - : socket_(socket), + : handler_base_from_member(handler), + socket_(socket), io_service_(io_service), work_(io_service), buffers_(buffers), - flags_(flags), - handler_(handler) + flags_(flags) { } - bool operator()(const asio::error_code& result) + bool perform(asio::error_code& ec, + std::size_t& bytes_transferred) { // Check whether the operation was successful. - if (result) + if (ec) { - io_service_.post(bind_handler(handler_, result, 0)); + bytes_transferred = 0; return true; } @@ -597,7 +620,6 @@ public: } // Send the data. - asio::error_code ec; int bytes = socket_ops::send(socket_, bufs, i, flags_, ec); // Check if we need to run the operation again. @@ -605,17 +627,22 @@ public: || ec == asio::error::try_again) return false; - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); + bytes_transferred = (bytes < 0 ? 0 : bytes); return true; } + void complete(const asio::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + private: socket_type socket_; asio::io_service& io_service_; asio::io_service::work work_; ConstBufferSequence buffers_; socket_base::message_flags flags_; - Handler handler_; }; // Start an asynchronous send. The data being sent must be valid for the @@ -666,12 +693,59 @@ public: impl.flags_ |= implementation_type::internal_non_blocking; } - reactor_.start_write_op(impl.socket_, - send_handler( + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + send_operation( impl.socket_, this->get_io_service(), buffers, flags, handler)); } } + template + class null_buffers_operation : + public handler_base_from_member + { + public: + null_buffers_operation(asio::io_service& io_service, Handler handler) + : handler_base_from_member(handler), + work_(io_service) + { + } + + bool perform(asio::error_code&, + std::size_t& bytes_transferred) + { + bytes_transferred = 0; + return true; + } + + void complete(const asio::error_code& ec, + std::size_t bytes_transferred) + { + work_.get_io_service().post(bind_handler( + this->handler_, ec, bytes_transferred)); + } + + private: + asio::io_service::work work_; + }; + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + // Send a datagram to the specified endpoint. Returns the number of bytes // sent. template @@ -733,29 +807,48 @@ public: } } + // Wait until data can be sent without blocking. + size_t send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, + asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + template - class send_to_handler + class send_to_operation : + public handler_base_from_member { public: - send_to_handler(socket_type socket, asio::io_service& io_service, + send_to_operation(socket_type socket, asio::io_service& io_service, const ConstBufferSequence& buffers, const endpoint_type& endpoint, socket_base::message_flags flags, Handler handler) - : socket_(socket), + : handler_base_from_member(handler), + socket_(socket), io_service_(io_service), work_(io_service), buffers_(buffers), destination_(endpoint), - flags_(flags), - handler_(handler) + flags_(flags) { } - bool operator()(const asio::error_code& result) + bool perform(asio::error_code& ec, + std::size_t& bytes_transferred) { // Check whether the operation was successful. - if (result) + if (ec) { - io_service_.post(bind_handler(handler_, result, 0)); + bytes_transferred = 0; return true; } @@ -773,7 +866,6 @@ public: } // Send the data. - asio::error_code ec; int bytes = socket_ops::sendto(socket_, bufs, i, flags_, destination_.data(), destination_.size(), ec); @@ -782,10 +874,16 @@ public: || ec == asio::error::try_again) return false; - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); + bytes_transferred = (bytes < 0 ? 0 : bytes); return true; } + void complete(const asio::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + private: socket_type socket_; asio::io_service& io_service_; @@ -793,7 +891,6 @@ public: ConstBufferSequence buffers_; endpoint_type destination_; socket_base::message_flags flags_; - Handler handler_; }; // Start an asynchronous send. The data being sent must be valid for the @@ -824,13 +921,31 @@ public: impl.flags_ |= implementation_type::internal_non_blocking; } - reactor_.start_write_op(impl.socket_, - send_to_handler( + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + send_to_operation( impl.socket_, this->get_io_service(), buffers, destination, flags, handler)); } } + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + // Receive some data from the peer. Returns the number of bytes received. template size_t receive(implementation_type& impl, @@ -888,7 +1003,7 @@ public: return bytes_recvd; // Check for EOF. - if (bytes_recvd == 0) + if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM) { ec = asio::error::eof; return 0; @@ -906,28 +1021,48 @@ public: } } + // Wait until data can be received without blocking. + size_t receive(implementation_type& impl, const null_buffers&, + socket_base::message_flags, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + return 0; + } + template - class receive_handler + class receive_operation : + public handler_base_from_member { public: - receive_handler(socket_type socket, asio::io_service& io_service, - const MutableBufferSequence& buffers, socket_base::message_flags flags, - Handler handler) - : socket_(socket), + receive_operation(socket_type socket, int protocol_type, + asio::io_service& io_service, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, Handler handler) + : handler_base_from_member(handler), + socket_(socket), + protocol_type_(protocol_type), io_service_(io_service), work_(io_service), buffers_(buffers), - flags_(flags), - handler_(handler) + flags_(flags) { } - bool operator()(const asio::error_code& result) + bool perform(asio::error_code& ec, + std::size_t& bytes_transferred) { // Check whether the operation was successful. - if (result) + if (ec) { - io_service_.post(bind_handler(handler_, result, 0)); + bytes_transferred = 0; return true; } @@ -945,9 +1080,8 @@ public: } // Receive some data. - asio::error_code ec; int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec); - if (bytes == 0) + if (bytes == 0 && protocol_type_ == SOCK_STREAM) ec = asio::error::eof; // Check if we need to run the operation again. @@ -955,17 +1089,23 @@ public: || ec == asio::error::try_again) return false; - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); + bytes_transferred = (bytes < 0 ? 0 : bytes); return true; } + void complete(const asio::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + private: socket_type socket_; + int protocol_type_; asio::io_service& io_service_; asio::io_service::work work_; MutableBufferSequence buffers_; socket_base::message_flags flags_; - Handler handler_; }; // Start an asynchronous receive. The buffer for the data being received @@ -1019,19 +1159,44 @@ public: if (flags & socket_base::message_out_of_band) { - reactor_.start_except_op(impl.socket_, - receive_handler( - impl.socket_, this->get_io_service(), buffers, flags, handler)); + reactor_.start_except_op(impl.socket_, impl.reactor_data_, + receive_operation( + impl.socket_, impl.protocol_.type(), + this->get_io_service(), buffers, flags, handler)); } else { - reactor_.start_read_op(impl.socket_, - receive_handler( - impl.socket_, this->get_io_service(), buffers, flags, handler)); + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + receive_operation( + impl.socket_, impl.protocol_.type(), + this->get_io_service(), buffers, flags, handler)); } } } + // Wait until data can be received without blocking. + template + void async_receive(implementation_type& impl, const null_buffers&, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else if (flags & socket_base::message_out_of_band) + { + reactor_.start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + // Receive a datagram with the endpoint of the sender. Returns the number of // bytes received. template @@ -1087,7 +1252,7 @@ public: } // Check for EOF. - if (bytes_recvd == 0) + if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM) { ec = asio::error::eof; return 0; @@ -1105,30 +1270,53 @@ public: } } + // Wait until data can be received without blocking. + size_t receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags, + asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + return 0; + } + template - class receive_from_handler + class receive_from_operation : + public handler_base_from_member { public: - receive_from_handler(socket_type socket, + receive_from_operation(socket_type socket, int protocol_type, asio::io_service& io_service, const MutableBufferSequence& buffers, endpoint_type& endpoint, socket_base::message_flags flags, Handler handler) - : socket_(socket), + : handler_base_from_member(handler), + socket_(socket), + protocol_type_(protocol_type), io_service_(io_service), work_(io_service), buffers_(buffers), sender_endpoint_(endpoint), - flags_(flags), - handler_(handler) + flags_(flags) { } - bool operator()(const asio::error_code& result) + bool perform(asio::error_code& ec, + std::size_t& bytes_transferred) { // Check whether the operation was successful. - if (result) + if (ec) { - io_service_.post(bind_handler(handler_, result, 0)); + bytes_transferred = 0; return true; } @@ -1147,10 +1335,9 @@ public: // Receive some data. std::size_t addr_len = sender_endpoint_.capacity(); - asio::error_code ec; int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_, sender_endpoint_.data(), &addr_len, ec); - if (bytes == 0) + if (bytes == 0 && protocol_type_ == SOCK_STREAM) ec = asio::error::eof; // Check if we need to run the operation again. @@ -1159,18 +1346,24 @@ public: return false; sender_endpoint_.resize(addr_len); - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); + bytes_transferred = (bytes < 0 ? 0 : bytes); return true; } + void complete(const asio::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + private: socket_type socket_; + int protocol_type_; asio::io_service& io_service_; asio::io_service::work work_; MutableBufferSequence buffers_; endpoint_type& sender_endpoint_; socket_base::message_flags flags_; - Handler handler_; }; // Start an asynchronous receive. The buffer for the data being received and @@ -1201,10 +1394,40 @@ public: impl.flags_ |= implementation_type::internal_non_blocking; } - reactor_.start_read_op(impl.socket_, - receive_from_handler( - impl.socket_, this->get_io_service(), buffers, - sender_endpoint, flags, handler)); + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + receive_from_operation( + impl.socket_, impl.protocol_.type(), this->get_io_service(), + buffers, sender_endpoint, flags, handler)); + } + } + + // Wait until data can be received without blocking. + template + void async_receive_from(implementation_type& impl, + const null_buffers&, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else + { + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + if (flags & socket_base::message_out_of_band) + { + reactor_.start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } } } @@ -1299,35 +1522,32 @@ public: } template - class accept_handler + class accept_operation : + public handler_base_from_member { public: - accept_handler(socket_type socket, asio::io_service& io_service, + accept_operation(socket_type socket, asio::io_service& io_service, Socket& peer, const protocol_type& protocol, endpoint_type* peer_endpoint, bool enable_connection_aborted, Handler handler) - : socket_(socket), + : handler_base_from_member(handler), + socket_(socket), io_service_(io_service), work_(io_service), peer_(peer), protocol_(protocol), peer_endpoint_(peer_endpoint), - enable_connection_aborted_(enable_connection_aborted), - handler_(handler) + enable_connection_aborted_(enable_connection_aborted) { } - bool operator()(const asio::error_code& result) + bool perform(asio::error_code& ec, std::size_t&) { // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result)); + if (ec) return true; - } // Accept the waiting connection. - asio::error_code ec; socket_holder new_socket; std::size_t addr_len = 0; if (peer_endpoint_) @@ -1363,10 +1583,14 @@ public: new_socket.release(); } - io_service_.post(bind_handler(handler_, ec)); return true; } + void complete(const asio::error_code& ec, std::size_t) + { + io_service_.post(bind_handler(this->handler_, ec)); + } + private: socket_type socket_; asio::io_service& io_service_; @@ -1375,7 +1599,6 @@ public: protocol_type protocol_; endpoint_type* peer_endpoint_; bool enable_connection_aborted_; - Handler handler_; }; // Start an asynchronous accept. The peer and peer_endpoint objects @@ -1409,8 +1632,8 @@ public: impl.flags_ |= implementation_type::internal_non_blocking; } - reactor_.start_read_op(impl.socket_, - accept_handler( + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + accept_operation( impl.socket_, this->get_io_service(), peer, impl.protocol_, peer_endpoint, (impl.flags_ & implementation_type::enable_connection_aborted) != 0, @@ -1444,70 +1667,52 @@ public: } template - class connect_handler + class connect_operation : + public handler_base_from_member { public: - connect_handler(socket_type socket, boost::shared_ptr completed, - asio::io_service& io_service, Reactor& reactor, Handler handler) - : socket_(socket), - completed_(completed), + connect_operation(socket_type socket, + asio::io_service& io_service, Handler handler) + : handler_base_from_member(handler), + socket_(socket), io_service_(io_service), - work_(io_service), - reactor_(reactor), - handler_(handler) + work_(io_service) { } - bool operator()(const asio::error_code& result) + bool perform(asio::error_code& ec, std::size_t&) { - // Check whether a handler has already been called for the connection. - // If it has, then we don't want to do anything in this handler. - if (*completed_) - return true; - - // Cancel the other reactor operation for the connection. - *completed_ = true; - reactor_.enqueue_cancel_ops_unlocked(socket_); - // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result)); + if (ec) return true; - } // Get the error code from the connect operation. int connect_error = 0; size_t connect_error_len = sizeof(connect_error); - asio::error_code ec; if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, &connect_error, &connect_error_len, ec) == socket_error_retval) - { - io_service_.post(bind_handler(handler_, ec)); return true; - } - // If connection failed then post the handler with the error code. + // The connection failed so the handler will be posted with an error code. if (connect_error) { ec = asio::error_code(connect_error, asio::error::get_system_category()); - io_service_.post(bind_handler(handler_, ec)); return true; } - // Post the result of the successful connection operation. - io_service_.post(bind_handler(handler_, ec)); return true; } + void complete(const asio::error_code& ec, std::size_t) + { + io_service_.post(bind_handler(this->handler_, ec)); + } + private: socket_type socket_; - boost::shared_ptr completed_; asio::io_service& io_service_; asio::io_service::work work_; - Reactor& reactor_; - Handler handler_; }; // Start an asynchronous connect. @@ -1551,10 +1756,9 @@ public: { // The connection is happening in the background, and we need to wait // until the socket becomes writeable. - boost::shared_ptr completed(new bool(false)); - reactor_.start_write_and_except_ops(impl.socket_, - connect_handler(impl.socket_, completed, - this->get_io_service(), reactor_, handler)); + reactor_.start_connect_op(impl.socket_, impl.reactor_data_, + connect_operation(impl.socket_, + this->get_io_service(), handler)); } else { diff --git a/libtorrent/include/libtorrent/asio/detail/reactor_op_queue.hpp b/libtorrent/include/asio/detail/reactor_op_queue.hpp similarity index 55% rename from libtorrent/include/libtorrent/asio/detail/reactor_op_queue.hpp rename to libtorrent/include/asio/detail/reactor_op_queue.hpp index b419c7c3f..034591d0d 100644 --- a/libtorrent/include/libtorrent/asio/detail/reactor_op_queue.hpp +++ b/libtorrent/include/asio/detail/reactor_op_queue.hpp @@ -22,6 +22,7 @@ #include "asio/detail/pop_options.hpp" #include "asio/error.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/hash_map.hpp" #include "asio/detail/noncopyable.hpp" @@ -37,36 +38,42 @@ public: reactor_op_queue() : operations_(), cancelled_operations_(0), - cleanup_operations_(0) + complete_operations_(0) { } // Add a new operation to the queue. Returns true if this is the only // operation for the given descriptor, in which case the reactor's event // demultiplexing function call may need to be interrupted and restarted. - template - bool enqueue_operation(Descriptor descriptor, Handler handler) + template + bool enqueue_operation(Descriptor descriptor, Operation operation) { - op_base* new_op = new op(descriptor, handler); + // Allocate and construct an object to wrap the handler. + typedef handler_alloc_traits > alloc_traits; + raw_handler_ptr raw_ptr(operation); + handler_ptr ptr(raw_ptr, descriptor, operation); typedef typename operation_map::iterator iterator; typedef typename operation_map::value_type value_type; std::pair entry = - operations_.insert(value_type(descriptor, new_op)); + operations_.insert(value_type(descriptor, ptr.get())); if (entry.second) + { + ptr.release(); return true; + } op_base* current_op = entry.first->second; while (current_op->next_) current_op = current_op->next_; - current_op->next_ = new_op; + current_op->next_ = ptr.release(); return false; } // Cancel all operations associated with the descriptor. Any operations // pending for the descriptor will be notified that they have been cancelled - // next time dispatch_cancellations is called. Returns true if any operations + // next time perform_cancellations is called. Returns true if any operations // were cancelled, in which case the reactor's event demultiplexing function // may need to be interrupted and restarted. bool cancel_operations(Descriptor descriptor) @@ -98,9 +105,9 @@ public: return operations_.find(descriptor) != operations_.end(); } - // Dispatch the first operation corresponding to the descriptor. Returns true + // Perform the first operation corresponding to the descriptor. Returns true // if there are more operations queued for the descriptor. - bool dispatch_operation(Descriptor descriptor, + bool perform_operation(Descriptor descriptor, const asio::error_code& result) { typename operation_map::iterator i = operations_.find(descriptor); @@ -108,9 +115,9 @@ public: { op_base* this_op = i->second; i->second = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - bool done = this_op->invoke(result); + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + bool done = this_op->perform(result); if (done) { // Operation has finished. @@ -127,8 +134,8 @@ public: else { // Operation wants to be called again. Leave it at the front of the - // queue for this descriptor, and remove from the cleanup list. - cleanup_operations_ = this_op->next_; + // queue for this descriptor, and remove from the completed list. + complete_operations_ = this_op->next_; this_op->next_ = i->second; i->second = this_op; return true; @@ -137,8 +144,8 @@ public: return false; } - // Dispatch all operations corresponding to the descriptor. - void dispatch_all_operations(Descriptor descriptor, + // Perform all operations corresponding to the descriptor. + void perform_all_operations(Descriptor descriptor, const asio::error_code& result) { typename operation_map::iterator i = operations_.find(descriptor); @@ -148,14 +155,14 @@ public: { op_base* this_op = i->second; i->second = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - bool done = this_op->invoke(result); + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + bool done = this_op->perform(result); if (!done) { // Operation has not finished yet, so leave at front of queue, and - // remove from the cleanup list. - cleanup_operations_ = this_op->next_; + // remove from the completed list. + complete_operations_ = this_op->next_; this_op->next_ = i->second; i->second = this_op; return; @@ -178,15 +185,15 @@ public: if (!descriptors.set(descriptor)) { asio::error_code ec(error::fd_set_failure); - dispatch_all_operations(descriptor, ec); + perform_all_operations(descriptor, ec); } } } - // Dispatch the operations corresponding to the ready file descriptors + // Perform the operations corresponding to the ready file descriptors // contained in the given descriptor set. template - void dispatch_descriptors(const Descriptor_Set& descriptors, + void perform_operations_for_descriptors(const Descriptor_Set& descriptors, const asio::error_code& result) { typename operation_map::iterator i = operations_.begin(); @@ -197,9 +204,9 @@ public: { op_base* this_op = op_iter->second; op_iter->second = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - bool done = this_op->invoke(result); + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + bool done = this_op->perform(result); if (done) { if (!op_iter->second) @@ -208,8 +215,8 @@ public: else { // Operation has not finished yet, so leave at front of queue, and - // remove from the cleanup list. - cleanup_operations_ = this_op->next_; + // remove from the completed list. + complete_operations_ = this_op->next_; this_op->next_ = op_iter->second; op_iter->second = this_op; } @@ -217,28 +224,28 @@ public: } } - // Dispatch any pending cancels for operations. - void dispatch_cancellations() + // Perform any pending cancels for operations. + void perform_cancellations() { while (cancelled_operations_) { op_base* this_op = cancelled_operations_; cancelled_operations_ = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - this_op->invoke(asio::error::operation_aborted); + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + this_op->perform(asio::error::operation_aborted); } } - // Destroy operations that are waiting to be cleaned up. - void cleanup_operations() + // Complete all operations that are waiting to be completed. + void complete_operations() { - while (cleanup_operations_) + while (complete_operations_) { - op_base* next_op = cleanup_operations_->next_; - cleanup_operations_->next_ = 0; - cleanup_operations_->destroy(); - cleanup_operations_ = next_op; + op_base* next_op = complete_operations_->next_; + complete_operations_->next_ = 0; + complete_operations_->complete(); + complete_operations_ = next_op; } } @@ -253,12 +260,12 @@ public: cancelled_operations_ = next_op; } - while (cleanup_operations_) + while (complete_operations_) { - op_base* next_op = cleanup_operations_->next_; - cleanup_operations_->next_ = 0; - cleanup_operations_->destroy(); - cleanup_operations_ = next_op; + op_base* next_op = complete_operations_->next_; + complete_operations_->next_ = 0; + complete_operations_->destroy(); + complete_operations_ = next_op; } typename operation_map::iterator i = operations_.begin(); @@ -290,28 +297,40 @@ private: } // Perform the operation. - bool invoke(const asio::error_code& result) + bool perform(const asio::error_code& result) { - return invoke_func_(this, result); + result_ = result; + return perform_func_(this, result_, bytes_transferred_); + } + + // Destroy the operation and post the handler. + void complete() + { + complete_func_(this, result_, bytes_transferred_); } // Destroy the operation. void destroy() { - return destroy_func_(this); + destroy_func_(this); } protected: - typedef bool (*invoke_func_type)(op_base*, - const asio::error_code&); + typedef bool (*perform_func_type)(op_base*, + asio::error_code&, std::size_t&); + typedef void (*complete_func_type)(op_base*, + const asio::error_code&, std::size_t); typedef void (*destroy_func_type)(op_base*); // Construct an operation for the given descriptor. - op_base(invoke_func_type invoke_func, + op_base(perform_func_type perform_func, complete_func_type complete_func, destroy_func_type destroy_func, Descriptor descriptor) - : invoke_func_(invoke_func), + : perform_func_(perform_func), + complete_func_(complete_func), destroy_func_(destroy_func), descriptor_(descriptor), + result_(), + bytes_transferred_(0), next_(0) { } @@ -324,48 +343,94 @@ private: private: friend class reactor_op_queue; - // The function to be called to dispatch the handler. - invoke_func_type invoke_func_; + // The function to be called to perform the operation. + perform_func_type perform_func_; - // The function to be called to delete the handler. + // The function to be called to delete the operation and post the handler. + complete_func_type complete_func_; + + // The function to be called to delete the operation. destroy_func_type destroy_func_; // The descriptor associated with the operation. Descriptor descriptor_; + // The result of the operation. + asio::error_code result_; + + // The number of bytes transferred in the operation. + std::size_t bytes_transferred_; + // The next operation for the same file descriptor. op_base* next_; }; - // Adaptor class template for using handlers in operations. - template + // Adaptor class template for operations. + template class op : public op_base { public: // Constructor. - op(Descriptor descriptor, Handler handler) - : op_base(&op::invoke_handler, - &op::destroy_handler, descriptor), - handler_(handler) + op(Descriptor descriptor, Operation operation) + : op_base(&op::do_perform, &op::do_complete, + &op::do_destroy, descriptor), + operation_(operation) { } - // Invoke the handler. - static bool invoke_handler(op_base* base, - const asio::error_code& result) + // Perform the operation. + static bool do_perform(op_base* base, + asio::error_code& result, std::size_t& bytes_transferred) { - return static_cast*>(base)->handler_(result); + return static_cast*>(base)->operation_.perform( + result, bytes_transferred); } - // Delete the handler. - static void destroy_handler(op_base* base) + // Destroy the operation and post the handler. + static void do_complete(op_base* base, + const asio::error_code& result, std::size_t bytes_transferred) { - delete static_cast*>(base); + // Take ownership of the operation object. + typedef op this_type; + this_type* this_op(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_op->operation_, this_op); + + // Make a copy of the error_code and the operation so that the memory can + // be deallocated before the upcall is made. + asio::error_code ec(result); + Operation operation(this_op->operation_); + + // Free the memory associated with the operation. + ptr.reset(); + + // Make the upcall. + operation.complete(ec, bytes_transferred); + } + + // Destroy the operation. + static void do_destroy(op_base* base) + { + // Take ownership of the operation object. + typedef op this_type; + this_type* this_op(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_op->operation_, this_op); + + // A sub-object of the operation may be the true owner of the memory + // associated with the operation. Consequently, a local copy of the + // operation is required to ensure that any owning sub-object remains + // valid until after we have deallocated the memory here. + Operation operation(this_op->operation_); + (void)operation; + + // Free the memory associated with the operation. + ptr.reset(); } private: - Handler handler_; + Operation operation_; }; // The type for a map of operations. @@ -377,8 +442,8 @@ private: // The list of operations that have been cancelled. op_base* cancelled_operations_; - // The list of operations to be destroyed. - op_base* cleanup_operations_; + // The list of operations waiting to be completed. + op_base* complete_operations_; }; } // namespace detail diff --git a/libtorrent/include/libtorrent/asio/detail/resolver_service.hpp b/libtorrent/include/asio/detail/resolver_service.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/resolver_service.hpp rename to libtorrent/include/asio/detail/resolver_service.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/scoped_lock.hpp b/libtorrent/include/asio/detail/scoped_lock.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/scoped_lock.hpp rename to libtorrent/include/asio/detail/scoped_lock.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/select_interrupter.hpp b/libtorrent/include/asio/detail/select_interrupter.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/select_interrupter.hpp rename to libtorrent/include/asio/detail/select_interrupter.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/select_reactor.hpp b/libtorrent/include/asio/detail/select_reactor.hpp similarity index 78% rename from libtorrent/include/libtorrent/asio/detail/select_reactor.hpp rename to libtorrent/include/asio/detail/select_reactor.hpp index a21cf93f5..78a364ee0 100644 --- a/libtorrent/include/libtorrent/asio/detail/select_reactor.hpp +++ b/libtorrent/include/asio/detail/select_reactor.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "asio/detail/pop_options.hpp" @@ -50,6 +51,11 @@ class select_reactor : public asio::detail::service_base > { public: + // Per-descriptor data. + struct per_descriptor_data + { + }; + // Constructor. select_reactor(asio::io_service& io_service) : asio::detail::service_base< @@ -106,7 +112,7 @@ public: // Register a socket with the reactor. Returns 0 on success, system error // code on failure. - int register_descriptor(socket_type descriptor) + int register_descriptor(socket_type, per_descriptor_data&) { return 0; } @@ -114,7 +120,8 @@ public: // Start a new read operation. The handler object will be invoked when the // given descriptor is ready to be read, or an error has occurred. template - void start_read_op(socket_type descriptor, Handler handler) + void start_read_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool /*allow_speculative_read*/ = true) { asio::detail::mutex::scoped_lock lock(mutex_); if (!shutdown_) @@ -125,7 +132,8 @@ public: // Start a new write operation. The handler object will be invoked when the // given descriptor is ready to be written, or an error has occurred. template - void start_write_op(socket_type descriptor, Handler handler) + void start_write_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool /*allow_speculative_write*/ = true) { asio::detail::mutex::scoped_lock lock(mutex_); if (!shutdown_) @@ -136,7 +144,8 @@ public: // Start a new exception operation. The handler object will be invoked when // the given descriptor has exception information, or an error has occurred. template - void start_except_op(socket_type descriptor, Handler handler) + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { asio::detail::mutex::scoped_lock lock(mutex_); if (!shutdown_) @@ -144,18 +153,74 @@ public: interrupter_.interrupt(); } + // Wrapper for connect handlers to enable the handler object to be placed + // in both the write and the except operation queues, but ensure that only + // one of the handlers is called. + template + class connect_handler_wrapper + { + public: + connect_handler_wrapper(socket_type descriptor, + boost::shared_ptr completed, + select_reactor& reactor, Handler handler) + : descriptor_(descriptor), + completed_(completed), + reactor_(reactor), + handler_(handler) + { + } + + bool perform(asio::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether one of the handlers has already been called. If it has, + // then we don't want to do anything in this handler. + if (*completed_) + { + completed_.reset(); // Indicate that this handler should not complete. + return true; + } + + // Cancel the other reactor operation for the connection. + *completed_ = true; + reactor_.enqueue_cancel_ops_unlocked(descriptor_); + + // Call the contained handler. + return handler_.perform(ec, bytes_transferred); + } + + void complete(const asio::error_code& ec, + std::size_t bytes_transferred) + { + if (completed_.get()) + handler_.complete(ec, bytes_transferred); + } + + private: + socket_type descriptor_; + boost::shared_ptr completed_; + select_reactor& reactor_; + Handler handler_; + }; + // Start new write and exception operations. The handler object will be // invoked when the given descriptor is ready for writing or has exception - // information available, or an error has occurred. + // information available, or an error has occurred. The handler will be called + // only once. template - void start_write_and_except_ops(socket_type descriptor, Handler handler) + void start_connect_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { asio::detail::mutex::scoped_lock lock(mutex_); if (!shutdown_) { - bool interrupt = write_op_queue_.enqueue_operation(descriptor, handler); - interrupt = except_op_queue_.enqueue_operation(descriptor, handler) - || interrupt; + boost::shared_ptr completed(new bool(false)); + connect_handler_wrapper wrapped_handler( + descriptor, completed, *this, handler); + bool interrupt = write_op_queue_.enqueue_operation( + descriptor, wrapped_handler); + interrupt = except_op_queue_.enqueue_operation( + descriptor, wrapped_handler) || interrupt; if (interrupt) interrupter_.interrupt(); } @@ -164,7 +229,7 @@ public: // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. - void cancel_ops(socket_type descriptor) + void cancel_ops(socket_type descriptor, per_descriptor_data&) { asio::detail::mutex::scoped_lock lock(mutex_); cancel_ops_unlocked(descriptor); @@ -173,8 +238,8 @@ public: // Enqueue cancellation of all operations associated with the given // descriptor. The handlers associated with the descriptor will be invoked // with the operation_aborted error. This function does not acquire the - // select_reactor's mutex, and so should only be used from within a reactor - // handler. + // select_reactor's mutex, and so should only be used when the reactor lock is + // already held. void enqueue_cancel_ops_unlocked(socket_type descriptor) { pending_cancellations_.push_back(descriptor); @@ -182,7 +247,7 @@ public: // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. - void close_descriptor(socket_type descriptor) + void close_descriptor(socket_type descriptor, per_descriptor_data&) { asio::detail::mutex::scoped_lock lock(mutex_); cancel_ops_unlocked(descriptor); @@ -245,16 +310,16 @@ private: // Dispatch any operation cancellations that were made while the select // loop was not running. - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) timer_queues_[i]->dispatch_cancellations(); // Check if the thread is supposed to stop. if (stop_thread_) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -263,7 +328,7 @@ private: if (!block && read_op_queue_.empty() && write_op_queue_.empty() && except_op_queue_.empty() && all_timer_queues_are_empty()) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -305,15 +370,15 @@ private: { // Exception operations must be processed first to ensure that any // out-of-band data is read before normal data. - except_op_queue_.dispatch_descriptors(except_fds, - asio::error_code()); - read_op_queue_.dispatch_descriptors(read_fds, - asio::error_code()); - write_op_queue_.dispatch_descriptors(write_fds, - asio::error_code()); - except_op_queue_.dispatch_cancellations(); - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); + except_op_queue_.perform_operations_for_descriptors( + except_fds, asio::error_code()); + read_op_queue_.perform_operations_for_descriptors( + read_fds, asio::error_code()); + write_op_queue_.perform_operations_for_descriptors( + write_fds, asio::error_code()); + except_op_queue_.perform_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); } for (std::size_t i = 0; i < timer_queues_.size(); ++i) { @@ -326,7 +391,7 @@ private: cancel_ops_unlocked(pending_cancellations_[i]); pending_cancellations_.clear(); - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); } // Run the select loop in the thread. @@ -411,16 +476,16 @@ private: // destructors may make calls back into this reactor. We make a copy of the // vector of timer queues since the original may be modified while the lock // is not held. - void cleanup_operations_and_timers( + void complete_operations_and_timers( asio::detail::mutex::scoped_lock& lock) { timer_queues_for_cleanup_ = timer_queues_; lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->cleanup_timers(); + timer_queues_for_cleanup_[i]->complete_timers(); } // Mutex to protect access to internal data. diff --git a/libtorrent/include/libtorrent/asio/detail/select_reactor_fwd.hpp b/libtorrent/include/asio/detail/select_reactor_fwd.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/select_reactor_fwd.hpp rename to libtorrent/include/asio/detail/select_reactor_fwd.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/service_base.hpp b/libtorrent/include/asio/detail/service_base.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/service_base.hpp rename to libtorrent/include/asio/detail/service_base.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/service_id.hpp b/libtorrent/include/asio/detail/service_id.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/service_id.hpp rename to libtorrent/include/asio/detail/service_id.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/service_registry.hpp b/libtorrent/include/asio/detail/service_registry.hpp similarity index 95% rename from libtorrent/include/libtorrent/asio/detail/service_registry.hpp rename to libtorrent/include/asio/detail/service_registry.hpp index dadcd4bf6..f517cbbf1 100644 --- a/libtorrent/include/libtorrent/asio/detail/service_registry.hpp +++ b/libtorrent/include/asio/detail/service_registry.hpp @@ -27,6 +27,12 @@ #include "asio/detail/noncopyable.hpp" #include "asio/detail/service_id.hpp" +#if defined(BOOST_NO_TYPEID) +# if !defined(ASIO_NO_TYPEID) +# define ASIO_NO_TYPEID +# endif // !defined(ASIO_NO_TYPEID) +#endif // defined(BOOST_NO_TYPEID) + namespace asio { namespace detail { @@ -156,6 +162,7 @@ private: service.id_ = &id; } +#if !defined(ASIO_NO_TYPEID) // Set a service's id. template void init_service_id(asio::io_service::service& service, @@ -164,6 +171,7 @@ private: service.type_info_ = &typeid(Service); service.id_ = 0; } +#endif // !defined(ASIO_NO_TYPEID) // Check if a service matches the given id. static bool service_id_matches( @@ -173,6 +181,7 @@ private: return service.id_ == &id; } +#if !defined(ASIO_NO_TYPEID) // Check if a service matches the given id. template static bool service_id_matches( @@ -181,6 +190,7 @@ private: { return service.type_info_ != 0 && *service.type_info_ == typeid(Service); } +#endif // !defined(ASIO_NO_TYPEID) // Mutex to protect access to internal data. mutable asio::detail::mutex mutex_; diff --git a/libtorrent/include/libtorrent/asio/detail/service_registry_fwd.hpp b/libtorrent/include/asio/detail/service_registry_fwd.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/service_registry_fwd.hpp rename to libtorrent/include/asio/detail/service_registry_fwd.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/signal_blocker.hpp b/libtorrent/include/asio/detail/signal_blocker.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/signal_blocker.hpp rename to libtorrent/include/asio/detail/signal_blocker.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/signal_init.hpp b/libtorrent/include/asio/detail/signal_init.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/signal_init.hpp rename to libtorrent/include/asio/detail/signal_init.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/socket_holder.hpp b/libtorrent/include/asio/detail/socket_holder.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/socket_holder.hpp rename to libtorrent/include/asio/detail/socket_holder.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp b/libtorrent/include/asio/detail/socket_ops.hpp similarity index 99% rename from libtorrent/include/libtorrent/asio/detail/socket_ops.hpp rename to libtorrent/include/asio/detail/socket_ops.hpp index 3d471b643..231bc61c5 100644 --- a/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp +++ b/libtorrent/include/asio/detail/socket_ops.hpp @@ -175,6 +175,22 @@ inline int connect(socket_type s, const socket_addr_type* addr, return result; } +inline int socketpair(int af, int type, int protocol, + socket_type sv[2], asio::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + (void)(af); + (void)(type); + (void)(protocol); + (void)(sv); + ec = asio::error::operation_not_supported; + return -1; +#else + clear_error(ec); + return error_wrapper(::socketpair(af, type, protocol, sv), ec); +#endif +} + inline int listen(socket_type s, int backlog, asio::error_code& ec) { clear_error(ec); diff --git a/libtorrent/include/libtorrent/asio/detail/socket_option.hpp b/libtorrent/include/asio/detail/socket_option.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/socket_option.hpp rename to libtorrent/include/asio/detail/socket_option.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/socket_select_interrupter.hpp b/libtorrent/include/asio/detail/socket_select_interrupter.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/socket_select_interrupter.hpp rename to libtorrent/include/asio/detail/socket_select_interrupter.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/socket_types.hpp b/libtorrent/include/asio/detail/socket_types.hpp similarity index 99% rename from libtorrent/include/libtorrent/asio/detail/socket_types.hpp rename to libtorrent/include/asio/detail/socket_types.hpp index b1e6e6781..b2acb6931 100644 --- a/libtorrent/include/libtorrent/asio/detail/socket_types.hpp +++ b/libtorrent/include/asio/detail/socket_types.hpp @@ -99,6 +99,7 @@ # endif # include # include +# include # include # include # include @@ -175,6 +176,7 @@ typedef in6_addr in6_addr_type; typedef ipv6_mreq in6_mreq_type; typedef sockaddr_in6 sockaddr_in6_type; typedef sockaddr_storage sockaddr_storage_type; +typedef sockaddr_un sockaddr_un_type; typedef addrinfo addrinfo_type; typedef int ioctl_arg_type; typedef uint32_t u_long_type; diff --git a/libtorrent/include/libtorrent/asio/detail/strand_service.hpp b/libtorrent/include/asio/detail/strand_service.hpp similarity index 96% rename from libtorrent/include/libtorrent/asio/detail/strand_service.hpp rename to libtorrent/include/asio/detail/strand_service.hpp index 42a5752f9..6deb040f6 100644 --- a/libtorrent/include/libtorrent/asio/detail/strand_service.hpp +++ b/libtorrent/include/asio/detail/strand_service.hpp @@ -20,6 +20,7 @@ #include "asio/detail/push_options.hpp" #include #include +#include #include #include "asio/detail/pop_options.hpp" @@ -54,19 +55,13 @@ public: #endif void add_ref() { - asio::detail::mutex::scoped_lock lock(mutex_); ++ref_count_; } void release() { - asio::detail::mutex::scoped_lock lock(mutex_); - --ref_count_; - if (ref_count_ == 0) - { - lock.unlock(); + if (--ref_count_ == 0) delete this; - } } private: @@ -147,7 +142,7 @@ public: strand_impl* prev_; // The reference count on the strand implementation. - size_t ref_count_; + boost::detail::atomic_count ref_count_; #if !defined(__BORLANDC__) friend void intrusive_ptr_add_ref(strand_impl* p) @@ -345,6 +340,16 @@ public: this_type* h(static_cast(base)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(h->handler_, h); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(h->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } private: diff --git a/libtorrent/include/libtorrent/asio/detail/task_io_service.hpp b/libtorrent/include/asio/detail/task_io_service.hpp similarity index 98% rename from libtorrent/include/libtorrent/asio/detail/task_io_service.hpp rename to libtorrent/include/asio/detail/task_io_service.hpp index 6889845ca..beba1f251 100644 --- a/libtorrent/include/libtorrent/asio/detail/task_io_service.hpp +++ b/libtorrent/include/asio/detail/task_io_service.hpp @@ -15,6 +15,10 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +#if defined(ASIO_ENABLE_TWO_LOCK_QUEUE) +#include "asio/detail/task_io_service_2lock.hpp" +#else // defined(ASIO_ENABLE_TWO_LOCK_QUEUE) + #include "asio/detail/push_options.hpp" #include "asio/error_code.hpp" @@ -416,4 +420,6 @@ private: #include "asio/detail/pop_options.hpp" +#endif // defined(ASIO_ENABLE_TWO_LOCK_QUEUE) + #endif // ASIO_DETAIL_TASK_IO_SERVICE_HPP diff --git a/libtorrent/include/asio/detail/task_io_service_2lock.hpp b/libtorrent/include/asio/detail/task_io_service_2lock.hpp new file mode 100644 index 000000000..9b0221bbb --- /dev/null +++ b/libtorrent/include/asio/detail/task_io_service_2lock.hpp @@ -0,0 +1,462 @@ +// +// task_io_service_2lock.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP +#define ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/error_code.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/call_stack.hpp" +#include "asio/detail/event.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/indirect_handler_queue.hpp" +#include "asio/detail/mutex.hpp" +#include "asio/detail/service_base.hpp" +#include "asio/detail/task_io_service_fwd.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include "asio/detail/pop_options.hpp" + +namespace asio { +namespace detail { + +// An alternative task_io_service implementation based on a two-lock queue. + +template +class task_io_service + : public asio::detail::service_base > +{ +public: + typedef indirect_handler_queue handler_queue; + + // Constructor. + task_io_service(asio::io_service& io_service) + : asio::detail::service_base >(io_service), + front_mutex_(), + back_mutex_(), + task_(use_service(io_service)), + outstanding_work_(0), + front_stopped_(false), + back_stopped_(false), + back_shutdown_(false), + back_first_idle_thread_(0), + back_task_thread_(0) + { + handler_queue_.push(&task_handler_); + } + + void init(size_t /*concurrency_hint*/) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + asio::detail::mutex::scoped_lock back_lock(back_mutex_); + back_shutdown_ = true; + back_lock.unlock(); + + // Destroy handler objects. + while (handler_queue::handler* h = handler_queue_.pop()) + if (h != &task_handler_) + h->destroy(); + + // Reset handler queue to initial state. + handler_queue_.push(&task_handler_); + } + + // Run the event loop until interrupted or no more work. + size_t run(asio::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = asio::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + idle_thread_info this_idle_thread; + this_idle_thread.next = 0; + + size_t n = 0; + while (do_one(&this_idle_thread, ec)) + if (n != (std::numeric_limits::max)()) + ++n; + return n; + } + + // Run until interrupted or one operation is performed. + size_t run_one(asio::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = asio::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + idle_thread_info this_idle_thread; + this_idle_thread.next = 0; + + return do_one(&this_idle_thread, ec); + } + + // Poll for operations without blocking. + size_t poll(asio::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = asio::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + size_t n = 0; + while (do_one(0, ec)) + if (n != (std::numeric_limits::max)()) + ++n; + return n; + } + + // Poll for one operation without blocking. + size_t poll_one(asio::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = asio::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + return do_one(0, ec); + } + + // Interrupt the event processing loop. + void stop() + { + asio::detail::mutex::scoped_lock front_lock(front_mutex_); + front_stopped_ = true; + front_lock.unlock(); + + asio::detail::mutex::scoped_lock back_lock(back_mutex_); + back_stopped_ = true; + interrupt_all_idle_threads(back_lock); + } + + // Reset in preparation for a subsequent run invocation. + void reset() + { + asio::detail::mutex::scoped_lock front_lock(front_mutex_); + front_stopped_ = false; + front_lock.unlock(); + + asio::detail::mutex::scoped_lock back_lock(back_mutex_); + back_stopped_ = false; + } + + // Notify that some work has started. + void work_started() + { + ++outstanding_work_; + } + + // Notify that some work has finished. + void work_finished() + { + if (--outstanding_work_ == 0) + stop(); + } + + // Request invocation of the given handler. + template + void dispatch(Handler handler) + { + if (call_stack::contains(this)) + asio_handler_invoke_helpers::invoke(handler, &handler); + else + post(handler); + } + + // Request invocation of the given handler and return immediately. + template + void post(Handler handler) + { + // Allocate and construct an operation to wrap the handler. + handler_queue::scoped_ptr ptr(handler_queue::wrap(handler)); + + asio::detail::mutex::scoped_lock back_lock(back_mutex_); + + // If the service has been shut down we silently discard the handler. + if (back_shutdown_) + return; + + // Add the handler to the end of the queue. + handler_queue_.push(ptr.get()); + ptr.release(); + + // An undelivered handler is treated as unfinished work. + ++outstanding_work_; + + // Wake up a thread to execute the handler. + interrupt_one_idle_thread(back_lock); + } + +private: + struct idle_thread_info; + + size_t do_one(idle_thread_info* this_idle_thread, + asio::error_code& ec) + { + bool task_has_run = false; + for (;;) + { + // The front lock must be held before we can pop items from the queue. + asio::detail::mutex::scoped_lock front_lock(front_mutex_); + if (front_stopped_) + { + ec = asio::error_code(); + return 0; + } + + if (handler_queue::handler* h = handler_queue_.pop()) + { + if (h == &task_handler_) + { + bool more_handlers = handler_queue_.poppable(); + unsigned long front_version = handler_queue_.front_version(); + front_lock.unlock(); + + // The task is always added to the back of the queue when we exit + // this block. + task_cleanup c(*this); + + // If we're polling and the task has already run then we're done. + bool polling = !this_idle_thread; + if (task_has_run && polling) + { + ec = asio::error_code(); + return 0; + } + + // If we're considering going idle we need to check whether the queue + // is still empty. If it is, add the thread to the list of idle + // threads. + if (!more_handlers && !polling) + { + asio::detail::mutex::scoped_lock back_lock(back_mutex_); + if (back_stopped_) + { + ec = asio::error_code(); + return 0; + } + else if (front_version == handler_queue_.back_version()) + { + back_task_thread_ = this_idle_thread; + } + else + { + more_handlers = true; + } + } + + // Run the task. May throw an exception. Only block if the handler + // queue is empty and we're not polling, otherwise we want to return + // as soon as possible. + task_has_run = true; + task_.run(!more_handlers && !polling); + } + else + { + front_lock.unlock(); + handler_cleanup c(*this); + + // Invoke the handler. May throw an exception. + h->invoke(); // invoke() deletes the handler object + + ec = asio::error_code(); + return 1; + } + } + else if (this_idle_thread) + { + unsigned long front_version = handler_queue_.front_version(); + front_lock.unlock(); + + // If we're considering going idle we need to check whether the queue + // is still empty. If it is, add the thread to the list of idle + // threads. + asio::detail::mutex::scoped_lock back_lock(back_mutex_); + if (back_stopped_) + { + ec = asio::error_code(); + return 0; + } + else if (front_version == handler_queue_.back_version()) + { + this_idle_thread->next = back_first_idle_thread_; + back_first_idle_thread_ = this_idle_thread; + this_idle_thread->wakeup_event.clear(back_lock); + this_idle_thread->wakeup_event.wait(back_lock); + } + } + else + { + ec = asio::error_code(); + return 0; + } + } + } + + // Interrupt a single idle thread. + void interrupt_one_idle_thread( + asio::detail::mutex::scoped_lock& back_lock) + { + if (back_first_idle_thread_) + { + idle_thread_info* idle_thread = back_first_idle_thread_; + back_first_idle_thread_ = idle_thread->next; + idle_thread->next = 0; + idle_thread->wakeup_event.signal(back_lock); + } + else if (back_task_thread_) + { + back_task_thread_ = 0; + task_.interrupt(); + } + } + + // Interrupt all idle threads. + void interrupt_all_idle_threads( + asio::detail::mutex::scoped_lock& back_lock) + { + while (back_first_idle_thread_) + { + idle_thread_info* idle_thread = back_first_idle_thread_; + back_first_idle_thread_ = idle_thread->next; + idle_thread->next = 0; + idle_thread->wakeup_event.signal(back_lock); + } + + if (back_task_thread_) + { + back_task_thread_ = 0; + task_.interrupt(); + } + } + + // Helper class to perform task-related operations on block exit. + class task_cleanup; + friend class task_cleanup; + class task_cleanup + { + public: + task_cleanup(task_io_service& task_io_svc) + : task_io_service_(task_io_svc) + { + } + + ~task_cleanup() + { + // Reinsert the task at the end of the handler queue. + asio::detail::mutex::scoped_lock back_lock( + task_io_service_.back_mutex_); + task_io_service_.back_task_thread_ = 0; + task_io_service_.handler_queue_.push(&task_io_service_.task_handler_); + } + + private: + task_io_service& task_io_service_; + }; + + // Helper class to perform handler-related operations on block exit. + class handler_cleanup + { + public: + handler_cleanup(task_io_service& task_io_svc) + : task_io_service_(task_io_svc) + { + } + + ~handler_cleanup() + { + task_io_service_.work_finished(); + } + + private: + task_io_service& task_io_service_; + }; + + // Mutexes to protect access to internal data. + asio::detail::mutex front_mutex_; + asio::detail::mutex back_mutex_; + + // The task to be run by this service. + Task& task_; + + // Handler object to represent the position of the task in the queue. + class task_handler + : public handler_queue::handler + { + public: + task_handler() + : handler_queue::handler(0, 0) + { + } + } task_handler_; + + // The count of unfinished work. + boost::detail::atomic_count outstanding_work_; + + // The queue of handlers that are ready to be delivered. + handler_queue handler_queue_; + + // Flag to indicate that the dispatcher has been stopped. + bool front_stopped_; + bool back_stopped_; + + // Flag to indicate that the dispatcher has been shut down. + bool back_shutdown_; + + // Structure containing information about an idle thread. + struct idle_thread_info + { + event wakeup_event; + idle_thread_info* next; + }; + + // The number of threads that are currently idle. + idle_thread_info* back_first_idle_thread_; + + // The thread that is currently blocked on the task. + idle_thread_info* back_task_thread_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/task_io_service_fwd.hpp b/libtorrent/include/asio/detail/task_io_service_fwd.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/task_io_service_fwd.hpp rename to libtorrent/include/asio/detail/task_io_service_fwd.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/thread.hpp b/libtorrent/include/asio/detail/thread.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/thread.hpp rename to libtorrent/include/asio/detail/thread.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/throw_error.hpp b/libtorrent/include/asio/detail/throw_error.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/throw_error.hpp rename to libtorrent/include/asio/detail/throw_error.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/timer_queue.hpp b/libtorrent/include/asio/detail/timer_queue.hpp similarity index 76% rename from libtorrent/include/libtorrent/asio/detail/timer_queue.hpp rename to libtorrent/include/asio/detail/timer_queue.hpp index ed12ddaa9..cdc94ab7a 100644 --- a/libtorrent/include/libtorrent/asio/detail/timer_queue.hpp +++ b/libtorrent/include/asio/detail/timer_queue.hpp @@ -27,6 +27,7 @@ #include "asio/detail/pop_options.hpp" #include "asio/error.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/hash_map.hpp" #include "asio/detail/noncopyable.hpp" #include "asio/detail/timer_queue_base.hpp" @@ -50,7 +51,7 @@ public: : timers_(), heap_(), cancelled_timers_(0), - cleanup_timers_(0) + complete_timers_(0) { } @@ -101,6 +102,8 @@ public: // Get the time for the timer that is earliest in the queue. virtual boost::posix_time::time_duration wait_duration() const { + if (heap_.empty()) + return boost::posix_time::pos_infin; return Time_Traits::to_posix_duration( Time_Traits::subtract(heap_[0]->time_, Time_Traits::now())); } @@ -113,10 +116,10 @@ public: { timer_base* t = heap_[0]; remove_timer(t); + t->result_ = asio::error_code(); t->prev_ = 0; - t->next_ = cleanup_timers_; - cleanup_timers_ = t; - t->invoke(asio::error_code()); + t->next_ = complete_timers_; + complete_timers_ = t; } } @@ -152,17 +155,23 @@ public: while (cancelled_timers_) { timer_base* this_timer = cancelled_timers_; + this_timer->result_ = asio::error::operation_aborted; cancelled_timers_ = this_timer->next_; - this_timer->next_ = cleanup_timers_; - cleanup_timers_ = this_timer; - this_timer->invoke(asio::error::operation_aborted); + this_timer->next_ = complete_timers_; + complete_timers_ = this_timer; } } - // Destroy timers that are waiting to be cleaned up. - virtual void cleanup_timers() + // Complete any timers that are waiting to be completed. + virtual void complete_timers() { - destroy_timer_list(cleanup_timers_); + while (complete_timers_) + { + timer_base* this_timer = complete_timers_; + complete_timers_ = this_timer->next_; + this_timer->next_ = 0; + this_timer->complete(); + } } // Destroy all timers. @@ -180,7 +189,7 @@ public: heap_.clear(); timers_.clear(); destroy_timer_list(cancelled_timers_); - destroy_timer_list(cleanup_timers_); + destroy_timer_list(complete_timers_); } private: @@ -189,27 +198,27 @@ private: class timer_base { public: - // Perform the timer operation and then destroy. - void invoke(const asio::error_code& result) + // Delete the timer and post the handler. + void complete() { - invoke_func_(this, result); + complete_func_(this, result_); } - // Destroy the timer operation. + // Delete the timer. void destroy() { destroy_func_(this); } protected: - typedef void (*invoke_func_type)(timer_base*, + typedef void (*complete_func_type)(timer_base*, const asio::error_code&); typedef void (*destroy_func_type)(timer_base*); // Constructor. - timer_base(invoke_func_type invoke_func, destroy_func_type destroy_func, + timer_base(complete_func_type complete_func, destroy_func_type destroy_func, const time_type& time, void* token) - : invoke_func_(invoke_func), + : complete_func_(complete_func), destroy_func_(destroy_func), time_(time), token_(token), @@ -228,13 +237,16 @@ private: private: friend class timer_queue; - // The function to be called to dispatch the handler. - invoke_func_type invoke_func_; + // The function to be called to delete the timer and post the handler. + complete_func_type complete_func_; - // The function to be called to destroy the handler. + // The function to be called to delete the timer. destroy_func_type destroy_func_; - // The time when the operation should fire. + // The result of the timer operation. + asio::error_code result_; + + // The time when the timer should fire. time_type time_; // The token associated with the timer. @@ -258,23 +270,52 @@ private: public: // Constructor. timer(const time_type& time, Handler handler, void* token) - : timer_base(&timer::invoke_handler, + : timer_base(&timer::complete_handler, &timer::destroy_handler, time, token), handler_(handler) { } - // Invoke the handler and then destroy it. - static void invoke_handler(timer_base* base, + // Delete the timer and post the handler. + static void complete_handler(timer_base* base, const asio::error_code& result) { - static_cast*>(base)->handler_(result); + // Take ownership of the timer object. + typedef timer this_type; + this_type* this_timer(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_timer->handler_, this_timer); + + // Make a copy of the error_code and the handler so that the memory can + // be deallocated before the upcall is made. + asio::error_code ec(result); + Handler handler(this_timer->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Make the upcall. + handler(ec); } - // Destroy the handler. + // Delete the timer. static void destroy_handler(timer_base* base) { - delete static_cast*>(base); + // Take ownership of the timer object. + typedef timer this_type; + this_type* this_timer(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_timer->handler_, this_timer); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(this_timer->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } private: @@ -383,8 +424,8 @@ private: // The list of timers to be cancelled. timer_base* cancelled_timers_; - // The list of timers to be destroyed. - timer_base* cleanup_timers_; + // The list of timers waiting to be completed. + timer_base* complete_timers_; }; } // namespace detail diff --git a/libtorrent/include/libtorrent/asio/detail/timer_queue_base.hpp b/libtorrent/include/asio/detail/timer_queue_base.hpp similarity index 93% rename from libtorrent/include/libtorrent/asio/detail/timer_queue_base.hpp rename to libtorrent/include/asio/detail/timer_queue_base.hpp index 30a2a216e..57f212b05 100644 --- a/libtorrent/include/libtorrent/asio/detail/timer_queue_base.hpp +++ b/libtorrent/include/asio/detail/timer_queue_base.hpp @@ -47,8 +47,8 @@ public: // Dispatch any pending cancels for timers. virtual void dispatch_cancellations() = 0; - // Destroy timers that are waiting to be cleaned up. - virtual void cleanup_timers() = 0; + // Complete all timers that are waiting to be completed. + virtual void complete_timers() = 0; // Destroy all timers. virtual void destroy_timers() = 0; diff --git a/libtorrent/include/libtorrent/asio/detail/tss_ptr.hpp b/libtorrent/include/asio/detail/tss_ptr.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/tss_ptr.hpp rename to libtorrent/include/asio/detail/tss_ptr.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/win_event.hpp b/libtorrent/include/asio/detail/win_event.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/win_event.hpp rename to libtorrent/include/asio/detail/win_event.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/win_fd_set_adapter.hpp b/libtorrent/include/asio/detail/win_fd_set_adapter.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/win_fd_set_adapter.hpp rename to libtorrent/include/asio/detail/win_fd_set_adapter.hpp diff --git a/libtorrent/include/asio/detail/win_iocp_handle_service.hpp b/libtorrent/include/asio/detail/win_iocp_handle_service.hpp new file mode 100644 index 000000000..99c472c34 --- /dev/null +++ b/libtorrent/include/asio/detail/win_iocp_handle_service.hpp @@ -0,0 +1,832 @@ +// +// win_iocp_handle_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP +#define ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/win_iocp_io_service_fwd.hpp" + +#if defined(ASIO_HAS_IOCP) + +#include "asio/detail/push_options.hpp" +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/buffer.hpp" +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/mutex.hpp" +#include "asio/detail/win_iocp_io_service.hpp" + +namespace asio { +namespace detail { + +class win_iocp_handle_service + : public asio::detail::service_base +{ +public: + // Base class for all operations. + typedef win_iocp_io_service::operation operation; + + // The native type of a stream handle. + typedef HANDLE native_type; + + // The implementation type of the stream handle. + class implementation_type + { + public: + // Default constructor. + implementation_type() + : handle_(INVALID_HANDLE_VALUE), + safe_cancellation_thread_id_(0), + next_(0), + prev_(0) + { + } + + private: + // Only this service will have access to the internal values. + friend class win_iocp_handle_service; + + // The native stream handle representation. + native_type handle_; + + // The ID of the thread from which it is safe to cancel asynchronous + // operations. 0 means no asynchronous operations have been started yet. + // ~0 means asynchronous operations have been started from more than one + // thread, and cancellation is not supported for the handle. + DWORD safe_cancellation_thread_id_; + + // Pointers to adjacent handle implementations in linked list. + implementation_type* next_; + implementation_type* prev_; + }; + + win_iocp_handle_service(asio::io_service& io_service) + : asio::detail::service_base(io_service), + iocp_service_(asio::use_service(io_service)), + mutex_(), + impl_list_(0) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + // Close all implementations, causing all operations to complete. + asio::detail::mutex::scoped_lock lock(mutex_); + implementation_type* impl = impl_list_; + while (impl) + { + close_for_destruction(*impl); + impl = impl->next_; + } + } + + // Construct a new handle implementation. + void construct(implementation_type& impl) + { + impl.handle_ = INVALID_HANDLE_VALUE; + impl.safe_cancellation_thread_id_ = 0; + + // Insert implementation into linked list of all implementations. + asio::detail::mutex::scoped_lock lock(mutex_); + impl.next_ = impl_list_; + impl.prev_ = 0; + if (impl_list_) + impl_list_->prev_ = &impl; + impl_list_ = &impl; + } + + // Destroy a handle implementation. + void destroy(implementation_type& impl) + { + close_for_destruction(impl); + + // Remove implementation from linked list of all implementations. + asio::detail::mutex::scoped_lock lock(mutex_); + if (impl_list_ == &impl) + impl_list_ = impl.next_; + if (impl.prev_) + impl.prev_->next_ = impl.next_; + if (impl.next_) + impl.next_->prev_= impl.prev_; + impl.next_ = 0; + impl.prev_ = 0; + } + + // Assign a native handle to a handle implementation. + asio::error_code assign(implementation_type& impl, + const native_type& native_handle, asio::error_code& ec) + { + if (is_open(impl)) + { + ec = asio::error::already_open; + return ec; + } + + if (iocp_service_.register_handle(native_handle, ec)) + return ec; + + impl.handle_ = native_handle; + ec = asio::error_code(); + return ec; + } + + // Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return impl.handle_ != INVALID_HANDLE_VALUE; + } + + // Destroy a handle implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + if (is_open(impl)) + { + if (!::CloseHandle(impl.handle_)) + { + DWORD last_error = ::GetLastError(); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + return ec; + } + + impl.handle_ = INVALID_HANDLE_VALUE; + impl.safe_cancellation_thread_id_ = 0; + } + + ec = asio::error_code(); + return ec; + } + + // Get the native handle representation. + native_type native(const implementation_type& impl) const + { + return impl.handle_; + } + + // Cancel all operations associated with the handle. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + } + else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress( + ::GetModuleHandleA("KERNEL32"), "CancelIoEx")) + { + // The version of Windows supports cancellation from any thread. + typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED); + cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr; + if (!cancel_io_ex(impl.handle_, 0)) + { + DWORD last_error = ::GetLastError(); + if (last_error == ERROR_NOT_FOUND) + { + // ERROR_NOT_FOUND means that there were no operations to be + // cancelled. We swallow this error to match the behaviour on other + // platforms. + ec = asio::error_code(); + } + else + { + ec = asio::error_code(last_error, + asio::error::get_system_category()); + } + } + else + { + ec = asio::error_code(); + } + } + else if (impl.safe_cancellation_thread_id_ == 0) + { + // No operations have been started, so there's nothing to cancel. + ec = asio::error_code(); + } + else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId()) + { + // Asynchronous operations have been started from the current thread only, + // so it is safe to try to cancel them using CancelIo. + if (!::CancelIo(impl.handle_)) + { + DWORD last_error = ::GetLastError(); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + } + else + { + ec = asio::error_code(); + } + } + else + { + // Asynchronous operations have been started from more than one thread, + // so cancellation is not safe. + ec = asio::error::operation_not_supported; + } + + return ec; + } + + class overlapped_wrapper + : public OVERLAPPED + { + public: + explicit overlapped_wrapper(asio::error_code& ec) + { + Internal = 0; + InternalHigh = 0; + Offset = 0; + OffsetHigh = 0; + + // Create a non-signalled manual-reset event, for GetOverlappedResult. + hEvent = ::CreateEvent(0, TRUE, FALSE, 0); + if (hEvent) + { + // As documented in GetQueuedCompletionStatus, setting the low order + // bit of this event prevents our synchronous writes from being treated + // as completion port events. + *reinterpret_cast(&hEvent) |= 1; + } + else + { + DWORD last_error = ::GetLastError(); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + } + } + + ~overlapped_wrapper() + { + if (hEvent) + { + ::CloseHandle(hEvent); + } + } + }; + + // Write the given data. Returns the number of bytes written. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return write_some_at(impl, 0, buffers, ec); + } + + // Write the given data at the specified offset. Returns the number of bytes + // written. + template + size_t write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Find first buffer of non-zero length. + asio::const_buffer buffer; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = asio::const_buffer(*iter); + if (asio::buffer_size(buffer) != 0) + break; + } + + // A request to write 0 bytes on a handle is a no-op. + if (asio::buffer_size(buffer) == 0) + { + ec = asio::error_code(); + return 0; + } + + overlapped_wrapper overlapped(ec); + if (ec) + { + return 0; + } + + // Write the data. + overlapped.Offset = offset & 0xFFFFFFFF; + overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::WriteFile(impl.handle_, + asio::buffer_cast(buffer), + static_cast(asio::buffer_size(buffer)), 0, &overlapped); + if (!ok) + { + DWORD last_error = ::GetLastError(); + if (last_error != ERROR_IO_PENDING) + { + ec = asio::error_code(last_error, + asio::error::get_system_category()); + return 0; + } + } + + // Wait for the operation to complete. + DWORD bytes_transferred = 0; + ok = ::GetOverlappedResult(impl.handle_, + &overlapped, &bytes_transferred, TRUE); + if (!ok) + { + DWORD last_error = ::GetLastError(); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + } + + ec = asio::error_code(); + return bytes_transferred; + } + + template + class write_operation + : public operation + { + public: + write_operation(win_iocp_io_service& io_service, + const ConstBufferSequence& buffers, Handler handler) + : operation(io_service, + &write_operation::do_completion_impl, + &write_operation::destroy_impl), + work_(io_service.get_io_service()), + buffers_(buffers), + handler_(handler) + { + } + + private: + static void do_completion_impl(operation* op, + DWORD last_error, size_t bytes_transferred) + { + // Take ownership of the operation object. + typedef write_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + +#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + typename ConstBufferSequence::const_iterator iter + = handler_op->buffers_.begin(); + typename ConstBufferSequence::const_iterator end + = handler_op->buffers_.end(); + while (iter != end) + { + asio::const_buffer buffer(*iter); + asio::buffer_cast(buffer); + ++iter; + } +#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Call the handler. + asio::error_code ec(last_error, + asio::error::get_system_category()); + asio_handler_invoke_helpers::invoke( + bind_handler(handler, ec, bytes_transferred), &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef write_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + asio::io_service::work work_; + ConstBufferSequence buffers_; + Handler handler_; + }; + + // Start an asynchronous write. The data being written must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + async_write_some_at(impl, 0, buffers, handler); + } + + // Start an asynchronous write at a specified offset. The data being written + // must be valid for the lifetime of the asynchronous operation. + template + void async_write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + return; + } + + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); + + // Allocate and construct an operation to wrap the handler. + typedef write_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr ptr(raw_ptr, iocp_service_, buffers, handler); + + // Find first buffer of non-zero length. + asio::const_buffer buffer; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = asio::const_buffer(*iter); + if (asio::buffer_size(buffer) != 0) + break; + } + + // A request to write 0 bytes on a handle is a no-op. + if (asio::buffer_size(buffer) == 0) + { + asio::io_service::work work(this->get_io_service()); + ptr.reset(); + asio::error_code error; + iocp_service_.post(bind_handler(handler, error, 0)); + return; + } + + // Write the data. + DWORD bytes_transferred = 0; + ptr.get()->Offset = offset & 0xFFFFFFFF; + ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::WriteFile(impl.handle_, + asio::buffer_cast(buffer), + static_cast(asio::buffer_size(buffer)), + &bytes_transferred, ptr.get()); + DWORD last_error = ::GetLastError(); + + // Check if the operation completed immediately. + if (!ok && last_error != ERROR_IO_PENDING) + { + asio::io_service::work work(this->get_io_service()); + ptr.reset(); + asio::error_code ec(last_error, + asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + + // Read some data. Returns the number of bytes received. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return read_some_at(impl, 0, buffers, ec); + } + + // Read some data at a specified offset. Returns the number of bytes received. + template + size_t read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Find first buffer of non-zero length. + asio::mutable_buffer buffer; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = asio::mutable_buffer(*iter); + if (asio::buffer_size(buffer) != 0) + break; + } + + // A request to read 0 bytes on a stream handle is a no-op. + if (asio::buffer_size(buffer) == 0) + { + ec = asio::error_code(); + return 0; + } + + overlapped_wrapper overlapped(ec); + if (ec) + { + return 0; + } + + // Read some data. + overlapped.Offset = offset & 0xFFFFFFFF; + overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::ReadFile(impl.handle_, + asio::buffer_cast(buffer), + static_cast(asio::buffer_size(buffer)), 0, &overlapped); + if (!ok) + { + DWORD last_error = ::GetLastError(); + if (last_error != ERROR_IO_PENDING) + { + if (last_error == ERROR_HANDLE_EOF) + { + ec = asio::error::eof; + } + else + { + ec = asio::error_code(last_error, + asio::error::get_system_category()); + } + return 0; + } + } + + // Wait for the operation to complete. + DWORD bytes_transferred = 0; + ok = ::GetOverlappedResult(impl.handle_, + &overlapped, &bytes_transferred, TRUE); + if (!ok) + { + DWORD last_error = ::GetLastError(); + if (last_error == ERROR_HANDLE_EOF) + { + ec = asio::error::eof; + } + else + { + ec = asio::error_code(last_error, + asio::error::get_system_category()); + } + } + + ec = asio::error_code(); + return bytes_transferred; + } + + template + class read_operation + : public operation + { + public: + read_operation(win_iocp_io_service& io_service, + const MutableBufferSequence& buffers, Handler handler) + : operation(io_service, + &read_operation< + MutableBufferSequence, Handler>::do_completion_impl, + &read_operation< + MutableBufferSequence, Handler>::destroy_impl), + work_(io_service.get_io_service()), + buffers_(buffers), + handler_(handler) + { + } + + private: + static void do_completion_impl(operation* op, + DWORD last_error, size_t bytes_transferred) + { + // Take ownership of the operation object. + typedef read_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + +#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + typename MutableBufferSequence::const_iterator iter + = handler_op->buffers_.begin(); + typename MutableBufferSequence::const_iterator end + = handler_op->buffers_.end(); + while (iter != end) + { + asio::mutable_buffer buffer(*iter); + asio::buffer_cast(buffer); + ++iter; + } +#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) + + // Check for the end-of-file condition. + asio::error_code ec(last_error, + asio::error::get_system_category()); + if (!ec && bytes_transferred == 0 || last_error == ERROR_HANDLE_EOF) + { + ec = asio::error::eof; + } + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Call the handler. + asio_handler_invoke_helpers::invoke( + bind_handler(handler, ec, bytes_transferred), &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef read_operation op_type; + op_type* handler_op(static_cast(op)); + typedef asio::detail::handler_alloc_traits< + Handler, op_type> alloc_traits; + asio::detail::handler_ptr ptr( + handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + asio::io_service::work work_; + MutableBufferSequence buffers_; + Handler handler_; + }; + + // Start an asynchronous read. The buffer for the data being received must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + async_read_some_at(impl, 0, buffers, handler); + } + + // Start an asynchronous read at a specified offset. The buffer for the data + // being received must be valid for the lifetime of the asynchronous + // operation. + template + void async_read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + return; + } + + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); + + // Allocate and construct an operation to wrap the handler. + typedef read_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr ptr(raw_ptr, iocp_service_, buffers, handler); + + // Find first buffer of non-zero length. + asio::mutable_buffer buffer; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = asio::mutable_buffer(*iter); + if (asio::buffer_size(buffer) != 0) + break; + } + + // A request to receive 0 bytes on a stream handle is a no-op. + if (asio::buffer_size(buffer) == 0) + { + asio::io_service::work work(this->get_io_service()); + ptr.reset(); + asio::error_code error; + iocp_service_.post(bind_handler(handler, error, 0)); + return; + } + + // Read some data. + DWORD bytes_transferred = 0; + ptr.get()->Offset = offset & 0xFFFFFFFF; + ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::ReadFile(impl.handle_, + asio::buffer_cast(buffer), + static_cast(asio::buffer_size(buffer)), + &bytes_transferred, ptr.get()); + DWORD last_error = ::GetLastError(); + if (!ok && last_error != ERROR_IO_PENDING) + { + asio::io_service::work work(this->get_io_service()); + ptr.reset(); + asio::error_code ec(last_error, + asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + +private: + // Prevent the use of the null_buffers type with this service. + size_t write_some(implementation_type& impl, + const null_buffers& buffers, asio::error_code& ec); + size_t write_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, asio::error_code& ec); + template + void async_write_some(implementation_type& impl, + const null_buffers& buffers, Handler handler); + template + void async_write_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, Handler handler); + size_t read_some(implementation_type& impl, + const null_buffers& buffers, asio::error_code& ec); + size_t read_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, asio::error_code& ec); + template + void async_read_some(implementation_type& impl, + const null_buffers& buffers, Handler handler); + template + void async_read_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, Handler handler); + + // Helper function to close a handle when the associated object is being + // destroyed. + void close_for_destruction(implementation_type& impl) + { + if (is_open(impl)) + { + ::CloseHandle(impl.handle_); + impl.handle_ = INVALID_HANDLE_VALUE; + impl.safe_cancellation_thread_id_ = 0; + } + } + + // The IOCP service used for running asynchronous operations and dispatching + // handlers. + win_iocp_io_service& iocp_service_; + + // Mutex to protect access to the linked list of implementations. + asio::detail::mutex mutex_; + + // The head of a linked list of all implementations. + implementation_type* impl_list_; +}; + +} // namespace detail +} // namespace asio + +#endif // defined(ASIO_HAS_IOCP) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_iocp_io_service.hpp b/libtorrent/include/asio/detail/win_iocp_io_service.hpp similarity index 94% rename from libtorrent/include/libtorrent/asio/detail/win_iocp_io_service.hpp rename to libtorrent/include/asio/detail/win_iocp_io_service.hpp index 6dec9c9b4..7f6d631c0 100644 --- a/libtorrent/include/libtorrent/asio/detail/win_iocp_io_service.hpp +++ b/libtorrent/include/asio/detail/win_iocp_io_service.hpp @@ -149,9 +149,20 @@ public: } // Register a handle with the IO completion port. - void register_handle(HANDLE handle) + asio::error_code register_handle( + HANDLE handle, asio::error_code& ec) { - ::CreateIoCompletionPort(handle, iocp_.handle, 0, 0); + if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0) + { + DWORD last_error = ::GetLastError(); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + } + else + { + ec = asio::error_code(); + } + return ec; } // Run the event loop until stopped or no more work. @@ -424,7 +435,7 @@ private: { timer_queues_copy_[i]->dispatch_timers(); timer_queues_copy_[i]->dispatch_cancellations(); - timer_queues_copy_[i]->cleanup_timers(); + timer_queues_copy_[i]->complete_timers(); } } catch (...) @@ -504,16 +515,18 @@ private: } else { + // Relinquish responsibility for dispatching timers. If the io_service + // is not being stopped then the thread will get an opportunity to + // reacquire timer responsibility on the next loop iteration. + if (dispatching_timers) + { + ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id); + } + // The stopped_ flag is always checked to ensure that any leftover // interrupts from a previous run invocation are ignored. if (::InterlockedExchangeAdd(&stopped_, 0) != 0) { - // Relinquish responsibility for dispatching timers. - if (dispatching_timers) - { - ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id); - } - // Wake up next thread that is blocked on GetQueuedCompletionStatus. if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0)) { @@ -636,6 +649,16 @@ private: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } win_iocp_io_service& io_service_; diff --git a/libtorrent/include/libtorrent/asio/detail/win_iocp_io_service_fwd.hpp b/libtorrent/include/asio/detail/win_iocp_io_service_fwd.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/win_iocp_io_service_fwd.hpp rename to libtorrent/include/asio/detail/win_iocp_io_service_fwd.hpp diff --git a/libtorrent/include/asio/detail/win_iocp_serial_port_service.hpp b/libtorrent/include/asio/detail/win_iocp_serial_port_service.hpp new file mode 100644 index 000000000..55f32ae18 --- /dev/null +++ b/libtorrent/include/asio/detail/win_iocp_serial_port_service.hpp @@ -0,0 +1,292 @@ +// +// win_iocp_serial_port_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP +#define ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/detail/win_iocp_io_service_fwd.hpp" + +#if defined(ASIO_HAS_IOCP) + +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/win_iocp_handle_service.hpp" + +namespace asio { +namespace detail { + +// Extend win_iocp_handle_service to provide serial port support. +class win_iocp_serial_port_service + : public asio::detail::service_base +{ +public: + // The native type of a stream handle. + typedef win_iocp_handle_service::native_type native_type; + + // The implementation type of the stream handle. + typedef win_iocp_handle_service::implementation_type implementation_type; + + win_iocp_serial_port_service(asio::io_service& io_service) + : asio::detail::service_base< + win_iocp_serial_port_service>(io_service), + handle_service_( + asio::use_service(io_service)) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new handle implementation. + void construct(implementation_type& impl) + { + handle_service_.construct(impl); + } + + // Destroy a handle implementation. + void destroy(implementation_type& impl) + { + handle_service_.destroy(impl); + } + + // Open the serial port using the specified device name. + asio::error_code open(implementation_type& impl, + const std::string& device, asio::error_code& ec) + { + if (is_open(impl)) + { + ec = asio::error::already_open; + return ec; + } + + // For convenience, add a leading \\.\ sequence if not already present. + std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device; + + // Open a handle to the serial port. + ::HANDLE handle = ::CreateFileA(name.c_str(), + GENERIC_READ | GENERIC_WRITE, 0, 0, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + if (handle == INVALID_HANDLE_VALUE) + { + DWORD last_error = ::GetLastError(); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + return ec; + } + + // Determine the initial serial port parameters. + using namespace std; // For memcpy. + ::DCB dcb; + memset(&dcb, 0, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + if (!::GetCommState(handle, &dcb)) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(handle); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + return ec; + } + + // Set some default serial port parameters. This implementation does not + // support changing these, so they might as well be in a known state. + dcb.fBinary = TRUE; // Win32 only supports binary mode. + dcb.fDsrSensitivity = FALSE; + dcb.fNull = FALSE; // Do not ignore NULL characters. + dcb.fAbortOnError = FALSE; // Ignore serial framing errors. + if (!::SetCommState(handle, &dcb)) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(handle); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + return ec; + } + + // Set up timeouts so that the serial port will behave similarly to a + // network socket. Reads wait for at least one byte, then return with + // whatever they have. Writes return once everything is out the door. + ::COMMTIMEOUTS timeouts; + timeouts.ReadIntervalTimeout = 1; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + if (!::SetCommTimeouts(handle, &timeouts)) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(handle); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + return ec; + } + + // We're done. Take ownership of the serial port handle. + if (handle_service_.assign(impl, handle, ec)) + ::CloseHandle(handle); + return ec; + } + + // Assign a native handle to a handle implementation. + asio::error_code assign(implementation_type& impl, + const native_type& native_handle, asio::error_code& ec) + { + return handle_service_.assign(impl, native_handle, ec); + } + + // Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return handle_service_.is_open(impl); + } + + // Destroy a handle implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + return handle_service_.close(impl, ec); + } + + // Get the native handle representation. + native_type native(implementation_type& impl) + { + return handle_service_.native(impl); + } + + // Cancel all operations associated with the handle. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + return handle_service_.cancel(impl, ec); + } + + // Set an option on the serial port. + template + asio::error_code set_option(implementation_type& impl, + const SettableSerialPortOption& option, asio::error_code& ec) + { + using namespace std; // For memcpy. + + ::DCB dcb; + memset(&dcb, 0, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + if (!::GetCommState(handle_service_.native(impl), &dcb)) + { + DWORD last_error = ::GetLastError(); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + return ec; + } + + if (option.store(dcb, ec)) + return ec; + + if (!::SetCommState(handle_service_.native(impl), &dcb)) + { + DWORD last_error = ::GetLastError(); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + return ec; + } + + ec = asio::error_code(); + return ec; + } + + // Get an option from the serial port. + template + asio::error_code get_option(const implementation_type& impl, + GettableSerialPortOption& option, asio::error_code& ec) const + { + using namespace std; // For memcpy. + + ::DCB dcb; + memset(&dcb, 0, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + if (!::GetCommState(handle_service_.native(impl), &dcb)) + { + DWORD last_error = ::GetLastError(); + ec = asio::error_code(last_error, + asio::error::get_system_category()); + return ec; + } + + return option.load(dcb, ec); + } + + // Send a break sequence to the serial port. + asio::error_code send_break(implementation_type& impl, + asio::error_code& ec) + { + ec = asio::error::operation_not_supported; + return ec; + } + + // Write the given data. Returns the number of bytes sent. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return handle_service_.write_some(impl, buffers, ec); + } + + // Start an asynchronous write. The data being written must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + handle_service_.async_write_some(impl, buffers, handler); + } + + // Read some data. Returns the number of bytes received. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return handle_service_.read_some(impl, buffers, ec); + } + + // Start an asynchronous read. The buffer for the data being received must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + handle_service_.async_read_some(impl, buffers, handler); + } + +private: + // The handle service used for initiating asynchronous operations. + win_iocp_handle_service& handle_service_; +}; + +} // namespace detail +} // namespace asio + +#endif // defined(ASIO_HAS_IOCP) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_iocp_socket_service.hpp b/libtorrent/include/asio/detail/win_iocp_socket_service.hpp similarity index 83% rename from libtorrent/include/libtorrent/asio/detail/win_iocp_socket_service.hpp rename to libtorrent/include/asio/detail/win_iocp_socket_service.hpp index 770ca4899..13943bab0 100644 --- a/libtorrent/include/libtorrent/asio/detail/win_iocp_socket_service.hpp +++ b/libtorrent/include/asio/detail/win_iocp_socket_service.hpp @@ -24,6 +24,7 @@ #include "asio/detail/push_options.hpp" #include #include +#include #include #include "asio/detail/pop_options.hpp" @@ -112,6 +113,9 @@ public: endpoint_type remote_endpoint_; }; + // The type of the reactor used for connect operations. + typedef detail::select_reactor reactor_type; + // The implementation type of the socket. class implementation_type { @@ -155,6 +159,9 @@ public: // The protocol associated with the socket. protocol_type protocol_; + // Per-descriptor data used by the reactor. + reactor_type::per_descriptor_data reactor_data_; + #if defined(ASIO_ENABLE_CANCELIO) // The ID of the thread from which it is safe to cancel asynchronous // operations. 0 means no asynchronous operations have been started yet. @@ -168,9 +175,6 @@ public: implementation_type* prev_; }; - // The type of the reactor used for connect operations. - typedef detail::select_reactor reactor_type; - // The maximum number of buffers to support in a single operation. enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; @@ -251,7 +255,8 @@ public: return ec; HANDLE sock_as_handle = reinterpret_cast(sock.get()); - iocp_service_.register_handle(sock_as_handle); + if (iocp_service_.register_handle(sock_as_handle, ec)) + return ec; impl.socket_ = sock.release(); impl.flags_ = 0; @@ -272,7 +277,8 @@ public: return ec; } - iocp_service_.register_handle(native_socket.as_handle()); + if (iocp_service_.register_handle(native_socket.as_handle(), ec)) + return ec; impl.socket_ = native_socket; impl.flags_ = 0; @@ -301,7 +307,7 @@ public: interlocked_compare_exchange_pointer( reinterpret_cast(&reactor_), 0, 0)); if (reactor) - reactor->close_descriptor(impl.socket_); + reactor->close_descriptor(impl.socket_, impl.reactor_data_); if (socket_ops::close(impl.socket_, ec) == socket_error_retval) return ec; @@ -331,6 +337,7 @@ public: if (!is_open(impl)) { ec = asio::error::bad_descriptor; + return ec; } else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress( ::GetModuleHandleA("KERNEL32"), "CancelIoEx")) @@ -699,6 +706,22 @@ public: return bytes_transferred; } + // Wait until data can be sent without blocking. + size_t send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + template class send_operation : public operation @@ -775,6 +798,16 @@ public: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } asio::io_service::work work_; @@ -857,6 +890,65 @@ public: } } + template + class null_buffers_operation + { + public: + null_buffers_operation(asio::io_service& io_service, Handler handler) + : work_(io_service), + handler_(handler) + { + } + + bool perform(asio::error_code&, + std::size_t& bytes_transferred) + { + bytes_transferred = 0; + return true; + } + + void complete(const asio::error_code& ec, + std::size_t bytes_transferred) + { + work_.get_io_service().post(bind_handler( + handler_, ec, bytes_transferred)); + } + + private: + asio::io_service::work work_; + Handler handler_; + }; + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + reactor->start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + // Send a datagram to the specified endpoint. Returns the number of bytes // sent. template @@ -901,6 +993,23 @@ public: return bytes_transferred; } + // Wait until data can be sent without blocking. + size_t send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, + asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + template class send_to_operation : public operation @@ -968,6 +1077,16 @@ public: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } asio::io_service::work work_; @@ -1037,6 +1156,36 @@ public: } } + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + reactor->start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + // Receive some data from the peer. Returns the number of bytes received. template size_t receive(implementation_type& impl, @@ -1086,7 +1235,7 @@ public: asio::error::get_system_category()); return 0; } - if (bytes_transferred == 0) + if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM) { ec = asio::error::eof; return 0; @@ -1096,12 +1245,28 @@ public: return bytes_transferred; } + // Wait until data can be received without blocking. + size_t receive(implementation_type& impl, const null_buffers&, + socket_base::message_flags, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + return 0; + } + template class receive_operation : public operation { public: - receive_operation(win_iocp_io_service& io_service, + receive_operation(int protocol_type, win_iocp_io_service& io_service, weak_cancel_token_type cancel_token, const MutableBufferSequence& buffers, Handler handler) : operation(io_service, @@ -1109,6 +1274,7 @@ public: MutableBufferSequence, Handler>::do_completion_impl, &receive_operation< MutableBufferSequence, Handler>::destroy_impl), + protocol_type_(protocol_type), work_(io_service.get_io_service()), cancel_token_(cancel_token), buffers_(buffers), @@ -1156,7 +1322,9 @@ public: } // Check for connection closed. - else if (!ec && bytes_transferred == 0) + else if (!ec && bytes_transferred == 0 + && handler_op->protocol_type_ == SOCK_STREAM + && !boost::is_same::value) { ec = asio::error::eof; } @@ -1180,8 +1348,19 @@ public: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } + int protocol_type_; asio::io_service::work work_; weak_cancel_token_type cancel_token_; MutableBufferSequence buffers_; @@ -1214,8 +1393,9 @@ public: typedef receive_operation value_type; typedef handler_alloc_traits alloc_traits; raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, iocp_service_, - impl.cancel_token_, buffers, handler); + int protocol_type = impl.protocol_.type(); + handler_ptr ptr(raw_ptr, protocol_type, + iocp_service_, impl.cancel_token_, buffers, handler); // Copy buffers into WSABUF array. ::WSABUF bufs[max_buffers]; @@ -1261,6 +1441,85 @@ public: } } + // Wait until data can be received without blocking. + template + void async_receive(implementation_type& impl, const null_buffers& buffers, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else if (impl.protocol_.type() == SOCK_STREAM) + { + // For stream sockets on Windows, we may issue a 0-byte overlapped + // WSARecv to wait until there is data available on the socket. + +#if defined(ASIO_ENABLE_CANCELIO) + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); +#endif // defined(ASIO_ENABLE_CANCELIO) + + // Allocate and construct an operation to wrap the handler. + typedef receive_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + int protocol_type = impl.protocol_.type(); + handler_ptr ptr(raw_ptr, protocol_type, + iocp_service_, impl.cancel_token_, buffers, handler); + + // Issue a receive operation with an empty buffer. + ::WSABUF buf = { 0, 0 }; + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int result = ::WSARecv(impl.socket_, &buf, 1, + &bytes_transferred, &recv_flags, ptr.get(), 0); + DWORD last_error = ::WSAGetLastError(); + if (result != 0 && last_error != WSA_IO_PENDING) + { + asio::io_service::work work(this->get_io_service()); + ptr.reset(); + asio::error_code ec(last_error, + asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + if (flags & socket_base::message_out_of_band) + { + reactor->start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor->start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + } + // Receive a datagram with the endpoint of the sender. Returns the number of // bytes received. template @@ -1302,7 +1561,7 @@ public: asio::error::get_system_category()); return 0; } - if (bytes_transferred == 0) + if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM) { ec = asio::error::eof; return 0; @@ -1314,12 +1573,32 @@ public: return bytes_transferred; } + // Wait until data can be received without blocking. + size_t receive_from(implementation_type& impl, + const null_buffers&, endpoint_type& sender_endpoint, + socket_base::message_flags, asio::error_code& ec) + { + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + return 0; + } + template class receive_from_operation : public operation { public: - receive_from_operation(win_iocp_io_service& io_service, + receive_from_operation(int protocol_type, win_iocp_io_service& io_service, endpoint_type& endpoint, const MutableBufferSequence& buffers, Handler handler) : operation(io_service, @@ -1327,6 +1606,7 @@ public: MutableBufferSequence, Handler>::do_completion_impl, &receive_from_operation< MutableBufferSequence, Handler>::destroy_impl), + protocol_type_(protocol_type), endpoint_(endpoint), endpoint_size_(static_cast(endpoint.capacity())), work_(io_service.get_io_service()), @@ -1373,7 +1653,8 @@ public: } // Check for connection closed. - if (!ec && bytes_transferred == 0) + if (!ec && bytes_transferred == 0 + && handler_op->protocol_type_ == SOCK_STREAM) { ec = asio::error::eof; } @@ -1400,8 +1681,19 @@ public: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } + int protocol_type_; endpoint_type& endpoint_; int endpoint_size_; asio::io_service::work work_; @@ -1436,8 +1728,9 @@ public: typedef receive_from_operation value_type; typedef handler_alloc_traits alloc_traits; raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, iocp_service_, - sender_endp, buffers, handler); + int protocol_type = impl.protocol_.type(); + handler_ptr ptr(raw_ptr, protocol_type, + iocp_service_, sender_endp, buffers, handler); // Copy buffers into WSABUF array. ::WSABUF bufs[max_buffers]; @@ -1472,6 +1765,48 @@ public: } } + // Wait until data can be received without blocking. + template + void async_receive_from(implementation_type& impl, + const null_buffers&, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + asio::error::bad_descriptor, 0)); + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + if (flags & socket_base::message_out_of_band) + { + reactor->start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor->start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + } + // Accept a new connection. template asio::error_code accept(implementation_type& impl, Socket& peer, @@ -1492,7 +1827,6 @@ public: for (;;) { - asio::error_code ec; socket_holder new_socket; std::size_t addr_len = 0; if (peer_endpoint) @@ -1570,8 +1904,7 @@ public: } private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) + static void do_completion_impl(operation* op, DWORD last_error, size_t) { // Take ownership of the operation object. typedef accept_operation op_type; @@ -1714,6 +2047,16 @@ public: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } win_iocp_io_service& io_service_; @@ -1832,58 +2175,38 @@ public: } template - class connect_handler + class connect_operation { public: - connect_handler(socket_type socket, bool user_set_non_blocking, - boost::shared_ptr completed, - asio::io_service& io_service, - reactor_type& reactor, Handler handler) + connect_operation(socket_type socket, bool user_set_non_blocking, + asio::io_service& io_service, Handler handler) : socket_(socket), user_set_non_blocking_(user_set_non_blocking), - completed_(completed), io_service_(io_service), - reactor_(reactor), work_(io_service), handler_(handler) { } - bool operator()(const asio::error_code& result) + bool perform(asio::error_code& ec, + std::size_t& bytes_transferred) { - // Check whether a handler has already been called for the connection. - // If it has, then we don't want to do anything in this handler. - if (*completed_) - return true; - - // Cancel the other reactor operation for the connection. - *completed_ = true; - reactor_.enqueue_cancel_ops_unlocked(socket_); - // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result)); + if (ec) return true; - } // Get the error code from the connect operation. int connect_error = 0; size_t connect_error_len = sizeof(connect_error); - asio::error_code ec; if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, &connect_error, &connect_error_len, ec) == socket_error_retval) - { - io_service_.post(bind_handler(handler_, ec)); return true; - } // If connection failed then post the handler with the error code. if (connect_error) { ec = asio::error_code(connect_error, asio::error::get_system_category()); - io_service_.post(bind_handler(handler_, ec)); return true; } @@ -1892,24 +2215,23 @@ public: { ioctl_arg_type non_blocking = 0; if (socket_ops::ioctl(socket_, FIONBIO, &non_blocking, ec)) - { - io_service_.post(bind_handler(handler_, ec)); return true; - } } // Post the result of the successful connection operation. ec = asio::error_code(); - io_service_.post(bind_handler(handler_, ec)); return true; } + void complete(const asio::error_code& ec, std::size_t) + { + io_service_.post(bind_handler(handler_, ec)); + } + private: socket_type socket_; bool user_set_non_blocking_; - boost::shared_ptr completed_; asio::io_service& io_service_; - reactor_type& reactor_; asio::io_service::work work_; Handler handler_; }; @@ -1977,11 +2299,11 @@ public: // The connection is happening in the background, and we need to wait // until the socket becomes writeable. boost::shared_ptr completed(new bool(false)); - reactor->start_write_and_except_ops(impl.socket_, - connect_handler( + reactor->start_connect_op(impl.socket_, impl.reactor_data_, + connect_operation( impl.socket_, (impl.flags_ & implementation_type::user_set_non_blocking) != 0, - completed, this->get_io_service(), *reactor, handler)); + this->get_io_service(), handler)); } else { @@ -2012,7 +2334,7 @@ private: interlocked_compare_exchange_pointer( reinterpret_cast(&reactor_), 0, 0)); if (reactor) - reactor->close_descriptor(impl.socket_); + reactor->close_descriptor(impl.socket_, impl.reactor_data_); // The socket destructor must not block. If the user has changed the // linger option to block in the foreground, we will change it back to the diff --git a/libtorrent/include/libtorrent/asio/detail/win_mutex.hpp b/libtorrent/include/asio/detail/win_mutex.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/win_mutex.hpp rename to libtorrent/include/asio/detail/win_mutex.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/win_signal_blocker.hpp b/libtorrent/include/asio/detail/win_signal_blocker.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/win_signal_blocker.hpp rename to libtorrent/include/asio/detail/win_signal_blocker.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/win_thread.hpp b/libtorrent/include/asio/detail/win_thread.hpp similarity index 58% rename from libtorrent/include/libtorrent/asio/detail/win_thread.hpp rename to libtorrent/include/asio/detail/win_thread.hpp index acd8b51e3..17d912565 100644 --- a/libtorrent/include/libtorrent/asio/detail/win_thread.hpp +++ b/libtorrent/include/asio/detail/win_thread.hpp @@ -43,17 +43,53 @@ class win_thread : private noncopyable { public: + // The purpose of the thread. + enum purpose { internal, external }; + // Constructor. template - win_thread(Function f) + win_thread(Function f, purpose p = internal) + : exit_event_(0) { std::auto_ptr arg(new func(f)); + + ::HANDLE entry_event = 0; + if (p == internal) + { + arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0); + if (!entry_event) + { + DWORD last_error = ::GetLastError(); + asio::system_error e( + asio::error_code(last_error, + asio::error::get_system_category()), + "thread.entry_event"); + boost::throw_exception(e); + } + + arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0); + if (!exit_event_) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(entry_event); + asio::system_error e( + asio::error_code(last_error, + asio::error::get_system_category()), + "thread.exit_event"); + boost::throw_exception(e); + } + } + unsigned int thread_id = 0; thread_ = reinterpret_cast(::_beginthreadex(0, 0, win_thread_function, arg.get(), 0, &thread_id)); if (!thread_) { DWORD last_error = ::GetLastError(); + if (entry_event) + ::CloseHandle(entry_event); + if (exit_event_) + ::CloseHandle(exit_event_); asio::system_error e( asio::error_code(last_error, asio::error::get_system_category()), @@ -61,18 +97,36 @@ public: boost::throw_exception(e); } arg.release(); + + if (entry_event) + { + ::WaitForSingleObject(entry_event, INFINITE); + ::CloseHandle(entry_event); + } } // Destructor. ~win_thread() { ::CloseHandle(thread_); + + // The exit_event_ handle is deliberately allowed to leak here since it + // is an error for the owner of an internal thread not to join() it. } // Wait for the thread to exit. void join() { - ::WaitForSingleObject(thread_, INFINITE); + if (exit_event_) + { + ::WaitForSingleObject(exit_event_, INFINITE); + ::CloseHandle(exit_event_); + ::TerminateThread(thread_, 0); + } + else + { + ::WaitForSingleObject(thread_, INFINITE); + } } private: @@ -83,6 +137,8 @@ private: public: virtual ~func_base() {} virtual void run() = 0; + ::HANDLE entry_event_; + ::HANDLE exit_event_; }; template @@ -105,13 +161,26 @@ private: }; ::HANDLE thread_; + ::HANDLE exit_event_; }; inline unsigned int __stdcall win_thread_function(void* arg) { std::auto_ptr func( static_cast(arg)); + + if (func->entry_event_) + ::SetEvent(func->entry_event_); + func->run(); + + if (HANDLE exit_event = func->exit_event_) + { + func.reset(); + ::SetEvent(exit_event); + ::Sleep(INFINITE); + } + return 0; } diff --git a/libtorrent/include/libtorrent/asio/detail/win_tss_ptr.hpp b/libtorrent/include/asio/detail/win_tss_ptr.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/win_tss_ptr.hpp rename to libtorrent/include/asio/detail/win_tss_ptr.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/wince_thread.hpp b/libtorrent/include/asio/detail/wince_thread.hpp similarity index 95% rename from libtorrent/include/libtorrent/asio/detail/wince_thread.hpp rename to libtorrent/include/asio/detail/wince_thread.hpp index d0b4a9f51..5a558b9ef 100644 --- a/libtorrent/include/libtorrent/asio/detail/wince_thread.hpp +++ b/libtorrent/include/asio/detail/wince_thread.hpp @@ -42,9 +42,12 @@ class wince_thread : private noncopyable { public: + // The purpose of the thread. + enum purpose { internal, external }; + // Constructor. template - wince_thread(Function f) + wince_thread(Function f, purpose = internal) { std::auto_ptr arg(new func(f)); DWORD thread_id = 0; diff --git a/libtorrent/include/libtorrent/asio/detail/winsock_init.hpp b/libtorrent/include/asio/detail/winsock_init.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/detail/winsock_init.hpp rename to libtorrent/include/asio/detail/winsock_init.hpp diff --git a/libtorrent/include/libtorrent/asio/detail/wrapped_handler.hpp b/libtorrent/include/asio/detail/wrapped_handler.hpp similarity index 90% rename from libtorrent/include/libtorrent/asio/detail/wrapped_handler.hpp rename to libtorrent/include/asio/detail/wrapped_handler.hpp index 0d8d03590..1b2e4dafc 100644 --- a/libtorrent/include/libtorrent/asio/detail/wrapped_handler.hpp +++ b/libtorrent/include/asio/detail/wrapped_handler.hpp @@ -127,22 +127,6 @@ public: Handler handler_; }; -template -inline void* asio_handler_allocate(std::size_t size, - wrapped_handler* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - wrapped_handler* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - template class rewrapped_handler { @@ -168,6 +152,22 @@ public: Context context_; }; +template +inline void* asio_handler_allocate(std::size_t size, + wrapped_handler* this_handler) +{ + return asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + wrapped_handler* this_handler) +{ + asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); +} + template inline void asio_handler_invoke(const Function& function, wrapped_handler* this_handler) @@ -177,6 +177,22 @@ inline void asio_handler_invoke(const Function& function, function, this_handler->handler_)); } +template +inline void* asio_handler_allocate(std::size_t size, + rewrapped_handler* this_handler) +{ + return asio_handler_alloc_helpers::allocate( + size, &this_handler->context_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + rewrapped_handler* this_handler) +{ + asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->context_); +} + template inline void asio_handler_invoke(const Function& function, rewrapped_handler* this_handler) diff --git a/libtorrent/include/libtorrent/asio/error.hpp b/libtorrent/include/asio/error.hpp similarity index 98% rename from libtorrent/include/libtorrent/asio/error.hpp rename to libtorrent/include/asio/error.hpp index 1487ed3d7..7a82a8849 100644 --- a/libtorrent/include/libtorrent/asio/error.hpp +++ b/libtorrent/include/asio/error.hpp @@ -105,6 +105,9 @@ enum basic_errors /// Message too long. message_size = ASIO_SOCKET_ERROR(EMSGSIZE), + /// The name was too long. + name_too_long = ASIO_SOCKET_ERROR(ENAMETOOLONG), + /// Network is down. network_down = ASIO_SOCKET_ERROR(ENETDOWN), diff --git a/libtorrent/include/libtorrent/asio/error_code.hpp b/libtorrent/include/asio/error_code.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/error_code.hpp rename to libtorrent/include/asio/error_code.hpp diff --git a/libtorrent/include/libtorrent/asio/handler_alloc_hook.hpp b/libtorrent/include/asio/handler_alloc_hook.hpp similarity index 98% rename from libtorrent/include/libtorrent/asio/handler_alloc_hook.hpp rename to libtorrent/include/asio/handler_alloc_hook.hpp index f49a78da9..8666cfb31 100644 --- a/libtorrent/include/libtorrent/asio/handler_alloc_hook.hpp +++ b/libtorrent/include/asio/handler_alloc_hook.hpp @@ -35,7 +35,7 @@ namespace asio { * * This default implementation is simply: * @code - * return ::operator new(bytes); + * return ::operator new(size); * @endcode * * @note All temporary objects associated with a handler will be deallocated diff --git a/libtorrent/include/libtorrent/asio/handler_invoke_hook.hpp b/libtorrent/include/asio/handler_invoke_hook.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/handler_invoke_hook.hpp rename to libtorrent/include/asio/handler_invoke_hook.hpp diff --git a/libtorrent/include/libtorrent/asio/impl/error_code.ipp b/libtorrent/include/asio/impl/error_code.ipp similarity index 100% rename from libtorrent/include/libtorrent/asio/impl/error_code.ipp rename to libtorrent/include/asio/impl/error_code.ipp diff --git a/libtorrent/include/libtorrent/asio/impl/io_service.ipp b/libtorrent/include/asio/impl/io_service.ipp similarity index 100% rename from libtorrent/include/libtorrent/asio/impl/io_service.ipp rename to libtorrent/include/asio/impl/io_service.ipp diff --git a/libtorrent/include/libtorrent/asio/impl/read.ipp b/libtorrent/include/asio/impl/read.ipp similarity index 100% rename from libtorrent/include/libtorrent/asio/impl/read.ipp rename to libtorrent/include/asio/impl/read.ipp diff --git a/libtorrent/include/asio/impl/read_at.ipp b/libtorrent/include/asio/impl/read_at.ipp new file mode 100644 index 000000000..2412487b5 --- /dev/null +++ b/libtorrent/include/asio/impl/read_at.ipp @@ -0,0 +1,337 @@ +// +// read_at.ipp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_READ_AT_IPP +#define ASIO_READ_AT_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/buffer.hpp" +#include "asio/completion_condition.hpp" +#include "asio/error.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/consuming_buffers.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/throw_error.hpp" + +namespace asio { + +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, asio::error_code& ec) +{ + asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> tmp(buffers); + std::size_t total_transferred = 0; + while (tmp.begin() != tmp.end()) + { + std::size_t bytes_transferred = d.read_some_at( + offset + total_transferred, tmp, ec); + tmp.consume(bytes_transferred); + total_transferred += bytes_transferred; + if (completion_condition(ec, total_transferred)) + return total_transferred; + } + ec = asio::error_code(); + return total_transferred; +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers) +{ + asio::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, buffers, transfer_all(), ec); + asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition) +{ + asio::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, buffers, completion_condition, ec); + asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, asio::basic_streambuf& b, + CompletionCondition completion_condition, asio::error_code& ec) +{ + std::size_t total_transferred = 0; + for (;;) + { + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + std::size_t bytes_transferred = d.read_some_at( + offset + total_transferred, b.prepare(bytes_available), ec); + b.commit(bytes_transferred); + total_transferred += bytes_transferred; + if (b.size() == b.max_size() + || completion_condition(ec, total_transferred)) + return total_transferred; + } +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, asio::basic_streambuf& b) +{ + asio::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, b, transfer_all(), ec); + asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, asio::basic_streambuf& b, + CompletionCondition completion_condition) +{ + asio::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, b, completion_condition, ec); + asio::detail::throw_error(ec); + return bytes_transferred; +} + +namespace detail +{ + template + class read_at_handler + { + public: + typedef asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> buffers_type; + + read_at_handler(AsyncRandomAccessReadDevice& stream, + boost::uint64_t offset, const buffers_type& buffers, + CompletionCondition completion_condition, ReadHandler handler) + : stream_(stream), + offset_(offset), + buffers_(buffers), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + buffers_.consume(bytes_transferred); + if (completion_condition_(ec, total_transferred_) + || buffers_.begin() == buffers_.end()) + { + handler_(ec, total_transferred_); + } + else + { + stream_.async_read_some_at( + offset_ + total_transferred_, buffers_, *this); + } + } + + //private: + AsyncRandomAccessReadDevice& stream_; + boost::uint64_t offset_; + buffers_type buffers_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_at_handler* this_handler) + { + return asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_at_handler* this_handler) + { + asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_at_handler* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, ReadHandler handler) +{ + asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> tmp(buffers); + d.async_read_some_at(offset, tmp, + detail::read_at_handler( + d, offset, tmp, completion_condition, handler)); +} + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + ReadHandler handler) +{ + async_read_at(d, offset, buffers, transfer_all(), handler); +} + +namespace detail +{ + template + class read_at_streambuf_handler + { + public: + read_at_streambuf_handler(AsyncRandomAccessReadDevice& stream, + boost::uint64_t offset, basic_streambuf& streambuf, + CompletionCondition completion_condition, ReadHandler handler) + : stream_(stream), + offset_(offset), + streambuf_(streambuf), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + streambuf_.commit(bytes_transferred); + if (streambuf_.size() == streambuf_.max_size() + || completion_condition_(ec, total_transferred_)) + { + handler_(ec, total_transferred_); + } + else + { + std::size_t bytes_available = + std::min(512, streambuf_.max_size() - streambuf_.size()); + stream_.async_read_some_at(offset_ + total_transferred_, + streambuf_.prepare(bytes_available), *this); + } + } + + //private: + AsyncRandomAccessReadDevice& stream_; + boost::uint64_t offset_; + asio::basic_streambuf& streambuf_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_at_streambuf_handler* this_handler) + { + return asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_at_streambuf_handler* this_handler) + { + asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_at_streambuf_handler* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, asio::basic_streambuf& b, + CompletionCondition completion_condition, ReadHandler handler) +{ + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + d.async_read_some_at(offset, b.prepare(bytes_available), + detail::read_at_streambuf_handler( + d, offset, b, completion_condition, handler)); +} + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, asio::basic_streambuf& b, + ReadHandler handler) +{ + async_read_at(d, offset, b, transfer_all(), handler); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_READ_AT_IPP diff --git a/libtorrent/include/libtorrent/asio/impl/read_until.ipp b/libtorrent/include/asio/impl/read_until.ipp similarity index 64% rename from libtorrent/include/libtorrent/asio/impl/read_until.ipp rename to libtorrent/include/asio/impl/read_until.ipp index fa549fe88..b88b14194 100644 --- a/libtorrent/include/libtorrent/asio/impl/read_until.ipp +++ b/libtorrent/include/asio/impl/read_until.ipp @@ -25,8 +25,8 @@ #include "asio/detail/pop_options.hpp" #include "asio/buffer.hpp" +#include "asio/buffers_iterator.hpp" #include "asio/detail/bind_handler.hpp" -#include "asio/detail/const_buffers_iterator.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/throw_error.hpp" @@ -54,24 +54,24 @@ std::size_t read_until(SyncReadStream& s, // Determine the range of the data to be searched. typedef typename asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, next_search_start); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); // Look for a match. - iterator iter = std::find(begin, end, delim); + iterator iter = std::find(start, end, delim); if (iter != end) { // Found a match. We're done. ec = asio::error_code(); - return iter.position() + 1; + return iter - begin + 1; } else { // No match. Next search can start with the new data. - next_search_start = end.position(); + next_search_start = end - begin; } // Check if buffer is full. @@ -146,33 +146,33 @@ std::size_t read_until(SyncReadStream& s, // Determine the range of the data to be searched. typedef typename asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, next_search_start); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); // Look for a match. std::pair result = asio::detail::partial_search( - begin, end, delim.begin(), delim.end()); + start, end, delim.begin(), delim.end()); if (result.first != end) { if (result.second) { // Full match. We're done. ec = asio::error_code(); - return result.first.position() + delim.length(); + return result.first - begin + delim.length(); } else { // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first.position(); + next_search_start = result.first - begin; } } else { // No match. Next search can start with the new data. - next_search_start = end.position(); + next_search_start = end - begin; } // Check if buffer is full. @@ -212,33 +212,33 @@ std::size_t read_until(SyncReadStream& s, // Determine the range of the data to be searched. typedef typename asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, next_search_start); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); // Look for a match. boost::match_results match_results; - if (boost::regex_search(begin, end, match_results, expr, + if (boost::regex_search(start, end, match_results, expr, boost::match_default | boost::match_partial)) { if (match_results[0].matched) { // Full match. We're done. ec = asio::error_code(); - return match_results[0].second.position(); + return match_results[0].second - begin; } else { // Partial match. Next search needs to start from beginning of match. - next_search_start = match_results[0].first.position(); + next_search_start = match_results[0].first - begin; } } else { // No match. Next search can start with the new data. - next_search_start = end.position(); + next_search_start = end - begin; } // Check if buffer is full. @@ -257,6 +257,73 @@ std::size_t read_until(SyncReadStream& s, } } +template +std::size_t read_until(SyncReadStream& s, + asio::basic_streambuf& b, + MatchCondition match_condition, asio::error_code& ec, + typename boost::enable_if >::type*) +{ + std::size_t next_search_start = 0; + for (;;) + { + // Determine the range of the data to be searched. + typedef typename asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); + + // Look for a match. + std::pair result = match_condition(start, end); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + ec = asio::error_code(); + return result.first - begin; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + ec = error::not_found; + return 0; + } + + // Need more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + b.commit(s.read_some(b.prepare(bytes_available), ec)); + if (ec) + return 0; + } +} + +template +inline std::size_t read_until(SyncReadStream& s, + asio::basic_streambuf& b, MatchCondition match_condition, + typename boost::enable_if >::type*) +{ + asio::error_code ec; + std::size_t bytes_transferred = read_until(s, b, match_condition, ec); + asio::detail::throw_error(ec); + return bytes_transferred; +} + namespace detail { template @@ -291,18 +358,18 @@ namespace detail // Determine the range of the data to be searched. typedef typename asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef asio::buffers_iterator iterator; const_buffers_type buffers = streambuf_.data(); - iterator begin(buffers, next_search_start_); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); // Look for a match. - iterator iter = std::find(begin, end, delim_); + iterator iter = std::find(start, end, delim_); if (iter != end) { // Found a match. We're done. - std::size_t bytes = iter.position() + 1; + std::size_t bytes = iter - begin + 1; handler_(ec, bytes); return; } @@ -317,7 +384,7 @@ namespace detail } // Next search can start with the new data. - next_search_start_ = end.position(); + next_search_start_ = end - begin; // Start a new asynchronous read operation to obtain more data. std::size_t bytes_available = @@ -369,11 +436,10 @@ void async_read_until(AsyncReadStream& s, // Determine the range of the data to be searched. typedef typename asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, 0); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); // Look for a match. iterator iter = std::find(begin, end, delim); @@ -381,7 +447,7 @@ void async_read_until(AsyncReadStream& s, { // Found a match. We're done. asio::error_code ec; - std::size_t bytes = iter.position() + 1; + std::size_t bytes = iter - begin + 1; s.io_service().post(detail::bind_handler(handler, ec, bytes)); return; } @@ -399,7 +465,7 @@ void async_read_until(AsyncReadStream& s, std::min(512, b.max_size() - b.size()); s.async_read_some(b.prepare(bytes_available), detail::read_until_delim_handler( - s, b, delim, end.position(), handler)); + s, b, delim, end - begin, handler)); } namespace detail @@ -437,34 +503,34 @@ namespace detail // Determine the range of the data to be searched. typedef typename asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef asio::buffers_iterator iterator; const_buffers_type buffers = streambuf_.data(); - iterator begin(buffers, next_search_start_); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); // Look for a match. std::pair result = asio::detail::partial_search( - begin, end, delim_.begin(), delim_.end()); + start, end, delim_.begin(), delim_.end()); if (result.first != end) { if (result.second) { // Full match. We're done. - std::size_t bytes = result.first.position() + delim_.length(); + std::size_t bytes = result.first - begin + delim_.length(); handler_(ec, bytes); return; } else { // Partial match. Next search needs to start from beginning of match. - next_search_start_ = result.first.position(); + next_search_start_ = result.first - begin; } } else { // No match. Next search can start with the new data. - next_search_start_ = end.position(); + next_search_start_ = end - begin; } // Check if buffer is full. @@ -527,11 +593,10 @@ void async_read_until(AsyncReadStream& s, // Determine the range of the data to be searched. typedef typename asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, 0); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); // Look for a match. std::size_t next_search_start; @@ -543,20 +608,20 @@ void async_read_until(AsyncReadStream& s, { // Full match. We're done. asio::error_code ec; - std::size_t bytes = result.first.position() + delim.length(); + std::size_t bytes = result.first - begin + delim.length(); s.io_service().post(detail::bind_handler(handler, ec, bytes)); return; } else { // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first.position(); + next_search_start = result.first - begin; } } else { // No match. Next search can start with the new data. - next_search_start = end.position(); + next_search_start = end - begin; } // Check if buffer is full. @@ -611,34 +676,34 @@ namespace detail // Determine the range of the data to be searched. typedef typename asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef asio::buffers_iterator iterator; const_buffers_type buffers = streambuf_.data(); - iterator begin(buffers, next_search_start_); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); // Look for a match. boost::match_results match_results; - if (boost::regex_search(begin, end, match_results, expr_, + if (boost::regex_search(start, end, match_results, expr_, boost::match_default | boost::match_partial)) { if (match_results[0].matched) { // Full match. We're done. - std::size_t bytes = match_results[0].second.position(); + std::size_t bytes = match_results[0].second - begin; handler_(ec, bytes); return; } else { // Partial match. Next search needs to start from beginning of match. - next_search_start_ = match_results[0].first.position(); + next_search_start_ = match_results[0].first - begin; } } else { // No match. Next search can start with the new data. - next_search_start_ = end.position(); + next_search_start_ = end - begin; } // Check if buffer is full. @@ -701,11 +766,10 @@ void async_read_until(AsyncReadStream& s, // Determine the range of the data to be searched. typedef typename asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, 0); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); // Look for a match. std::size_t next_search_start; @@ -717,20 +781,20 @@ void async_read_until(AsyncReadStream& s, { // Full match. We're done. asio::error_code ec; - std::size_t bytes = match_results[0].second.position(); + std::size_t bytes = match_results[0].second - begin; s.io_service().post(detail::bind_handler(handler, ec, bytes)); return; } else { // Partial match. Next search needs to start from beginning of match. - next_search_start = match_results[0].first.position(); + next_search_start = match_results[0].first - begin; } } else { // No match. Next search can start with the new data. - next_search_start = end.position(); + next_search_start = end - begin; } // Check if buffer is full. @@ -749,6 +813,182 @@ void async_read_until(AsyncReadStream& s, s, b, expr, next_search_start, handler)); } +namespace detail +{ + template + class read_until_match_handler + { + public: + read_until_match_handler(AsyncReadStream& stream, + asio::basic_streambuf& streambuf, + MatchCondition match_condition, std::size_t next_search_start, + ReadHandler handler) + : stream_(stream), + streambuf_(streambuf), + match_condition_(match_condition), + next_search_start_(next_search_start), + handler_(handler) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred) + { + // Check for errors. + if (ec) + { + std::size_t bytes = 0; + handler_(ec, bytes); + return; + } + + // Commit received data to streambuf's get area. + streambuf_.commit(bytes_transferred); + + // Determine the range of the data to be searched. + typedef typename asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef asio::buffers_iterator iterator; + const_buffers_type buffers = streambuf_.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); + + // Look for a match. + std::pair result = match_condition_(start, end); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + std::size_t bytes = result.first - begin; + handler_(ec, bytes); + return; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start_ = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start_ = end - begin; + } + + // Check if buffer is full. + if (streambuf_.size() == streambuf_.max_size()) + { + std::size_t bytes = 0; + asio::error_code ec(error::not_found); + handler_(ec, bytes); + return; + } + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, streambuf_.max_size() - streambuf_.size()); + stream_.async_read_some(streambuf_.prepare(bytes_available), *this); + } + + //private: + AsyncReadStream& stream_; + asio::basic_streambuf& streambuf_; + MatchCondition match_condition_; + std::size_t next_search_start_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_until_match_handler* this_handler) + { + return asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_until_match_handler* this_handler) + { + asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_until_match_handler* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +void async_read_until(AsyncReadStream& s, + asio::basic_streambuf& b, + MatchCondition match_condition, ReadHandler handler, + typename boost::enable_if >::type*) +{ + // Determine the range of the data to be searched. + typedef typename asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); + + // Look for a match. + std::size_t next_search_start; + std::pair result = match_condition(begin, end); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + asio::error_code ec; + std::size_t bytes = result.first - begin; + s.io_service().post(detail::bind_handler(handler, ec, bytes)); + return; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + asio::error_code ec(error::not_found); + s.io_service().post(detail::bind_handler(handler, ec, 0)); + return; + } + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + s.async_read_some(b.prepare(bytes_available), + detail::read_until_match_handler< + AsyncReadStream, Allocator, MatchCondition, ReadHandler>( + s, b, match_condition, next_search_start, handler)); +} + } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/libtorrent/include/asio/impl/serial_port_base.ipp b/libtorrent/include/asio/impl/serial_port_base.ipp new file mode 100644 index 000000000..8dd6083ee --- /dev/null +++ b/libtorrent/include/asio/impl/serial_port_base.ipp @@ -0,0 +1,541 @@ +// +// serial_port_base.ipp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_SERIAL_PORT_BASE_IPP +#define ASIO_SERIAL_PORT_BASE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +namespace asio { + +inline serial_port_base::baud_rate::baud_rate(unsigned int rate) + : value_(rate) +{ +} + +inline unsigned int serial_port_base::baud_rate::value() const +{ + return value_; +} + +inline asio::error_code serial_port_base::baud_rate::store( + ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + storage.BaudRate = value_; +#else + speed_t baud; + switch (value_) + { + // Do POSIX-specified rates first. + case 0: baud = B0; break; + case 50: baud = B50; break; + case 75: baud = B75; break; + case 110: baud = B110; break; + case 134: baud = B134; break; + case 150: baud = B150; break; + case 200: baud = B200; break; + case 300: baud = B300; break; + case 600: baud = B600; break; + case 1200: baud = B1200; break; + case 1800: baud = B1800; break; + case 2400: baud = B2400; break; + case 4800: baud = B4800; break; + case 9600: baud = B9600; break; + case 19200: baud = B19200; break; + case 38400: baud = B38400; break; + // And now the extended ones conditionally. +# ifdef B7200 + case 7200: baud = B7200; break; +# endif +# ifdef B14400 + case 14400: baud = B14400; break; +# endif +# ifdef B57600 + case 57600: baud = B57600; break; +# endif +# ifdef B115200 + case 115200: baud = B115200; break; +# endif +# ifdef B230400 + case 230400: baud = B230400; break; +# endif +# ifdef B460800 + case 460800: baud = B460800; break; +# endif +# ifdef B500000 + case 500000: baud = B500000; break; +# endif +# ifdef B576000 + case 576000: baud = B576000; break; +# endif +# ifdef B921600 + case 921600: baud = B921600; break; +# endif +# ifdef B1000000 + case 1000000: baud = B1000000; break; +# endif +# ifdef B1152000 + case 1152000: baud = B1152000; break; +# endif +# ifdef B2000000 + case 2000000: baud = B2000000; break; +# endif +# ifdef B3000000 + case 3000000: baud = B3000000; break; +# endif +# ifdef B3500000 + case 3500000: baud = B3500000; break; +# endif +# ifdef B4000000 + case 4000000: baud = B4000000; break; +# endif + default: + baud = B0; + ec = asio::error::invalid_argument; + return ec; + } +# if defined(_BSD_SOURCE) + ::cfsetspeed(&storage, baud); +# else + ::cfsetispeed(&storage, baud); + ::cfsetospeed(&storage, baud); +# endif +#endif + ec = asio::error_code(); + return ec; +} + +inline asio::error_code serial_port_base::baud_rate::load( + const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + value_ = storage.BaudRate; +#else + speed_t baud = ::cfgetospeed(&storage); + switch (baud) + { + // First do those specified by POSIX. + case B0: value_ = 0; break; + case B50: value_ = 50; break; + case B75: value_ = 75; break; + case B110: value_ = 110; break; + case B134: value_ = 134; break; + case B150: value_ = 150; break; + case B200: value_ = 200; break; + case B300: value_ = 300; break; + case B600: value_ = 600; break; + case B1200: value_ = 1200; break; + case B1800: value_ = 1800; break; + case B2400: value_ = 2400; break; + case B4800: value_ = 4800; break; + case B9600: value_ = 9600; break; + case B19200: value_ = 19200; break; + case B38400: value_ = 38400; break; + // Now conditionally handle a bunch of extended rates. +# ifdef B7200 + case B7200: value_ = 7200; break; +# endif +# ifdef B14400 + case B14400: value_ = 14400; break; +# endif +# ifdef B57600 + case B57600: value_ = 57600; break; +# endif +# ifdef B115200 + case B115200: value_ = 115200; break; +# endif +# ifdef B230400 + case B230400: value_ = 230400; break; +# endif +# ifdef B460800 + case B460800: value_ = 460800; break; +# endif +# ifdef B500000 + case B500000: value_ = 500000; break; +# endif +# ifdef B576000 + case B576000: value_ = 576000; break; +# endif +# ifdef B921600 + case B921600: value_ = 921600; break; +# endif +# ifdef B1000000 + case B1000000: value_ = 1000000; break; +# endif +# ifdef B1152000 + case B1152000: value_ = 1152000; break; +# endif +# ifdef B2000000 + case B2000000: value_ = 2000000; break; +# endif +# ifdef B3000000 + case B3000000: value_ = 3000000; break; +# endif +# ifdef B3500000 + case B3500000: value_ = 3500000; break; +# endif +# ifdef B4000000 + case B4000000: value_ = 4000000; break; +# endif + default: + value_ = 0; + ec = asio::error::invalid_argument; + return ec; + } +#endif + ec = asio::error_code(); + return ec; +} + +inline serial_port_base::flow_control::flow_control( + serial_port_base::flow_control::type t) + : value_(t) +{ + if (t != none && t != software && t != hardware) + throw std::out_of_range("invalid flow_control value"); +} + +inline serial_port_base::flow_control::type +serial_port_base::flow_control::value() const +{ + return value_; +} + +inline asio::error_code serial_port_base::flow_control::store( + ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + storage.fOutxCtsFlow = FALSE; + storage.fOutxDsrFlow = FALSE; + storage.fTXContinueOnXoff = TRUE; + storage.fDtrControl = DTR_CONTROL_ENABLE; + storage.fDsrSensitivity = FALSE; + storage.fOutX = FALSE; + storage.fInX = FALSE; + storage.fRtsControl = RTS_CONTROL_ENABLE; + switch (value_) + { + case none: + break; + case software: + storage.fOutX = TRUE; + storage.fInX = TRUE; + break; + case hardware: + storage.fOutxCtsFlow = TRUE; + storage.fRtsControl = RTS_CONTROL_HANDSHAKE; + break; + default: + break; + } +#else + switch (value_) + { + case none: + storage.c_iflag &= ~(IXOFF | IXON); +# if defined(_BSD_SOURCE) + storage.c_cflag &= ~CRTSCTS; +# endif + break; + case software: + storage.c_iflag |= IXOFF | IXON; +# if defined(_BSD_SOURCE) + storage.c_cflag &= ~CRTSCTS; +# endif + break; + case hardware: +# if defined(_BSD_SOURCE) + storage.c_iflag &= ~(IXOFF | IXON); + storage.c_cflag |= CRTSCTS; + break; +# else + ec = asio::error::operation_not_supported; + return ec; +# endif + default: + break; + } +#endif + ec = asio::error_code(); + return ec; +} + +inline asio::error_code serial_port_base::flow_control::load( + const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + if (storage.fOutX && storage.fInX) + { + value_ = software; + } + else if (storage.fOutxCtsFlow && storage.fRtsControl == RTS_CONTROL_HANDSHAKE) + { + value_ = hardware; + } + else + { + value_ = none; + } +#else + if (storage.c_iflag & (IXOFF | IXON)) + { + value_ = software; + } +# if defined(_BSD_SOURCE) + else if (storage.c_cflag & CRTSCTS) + { + value_ = hardware; + } +# endif + else + { + value_ = none; + } +#endif + ec = asio::error_code(); + return ec; +} + +inline serial_port_base::parity::parity(serial_port_base::parity::type t) + : value_(t) +{ + if (t != none && t != odd && t != even) + throw std::out_of_range("invalid parity value"); +} + +inline serial_port_base::parity::type serial_port_base::parity::value() const +{ + return value_; +} + +inline asio::error_code serial_port_base::parity::store( + ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + switch (value_) + { + case none: + storage.fParity = FALSE; + storage.Parity = NOPARITY; + break; + case odd: + storage.fParity = TRUE; + storage.Parity = ODDPARITY; + break; + case even: + storage.fParity = TRUE; + storage.Parity = EVENPARITY; + break; + default: + break; + } +#else + switch (value_) + { + case none: + storage.c_iflag |= IGNPAR; + storage.c_cflag &= ~(PARENB | PARODD); + break; + case even: + storage.c_iflag &= ~(IGNPAR | PARMRK); + storage.c_iflag |= INPCK; + storage.c_cflag |= PARENB; + storage.c_cflag &= ~PARODD; + break; + case odd: + storage.c_iflag &= ~(IGNPAR | PARMRK); + storage.c_iflag |= INPCK; + storage.c_cflag |= (PARENB | PARODD); + break; + default: + break; + } +#endif + ec = asio::error_code(); + return ec; +} + +inline asio::error_code serial_port_base::parity::load( + const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + if (storage.Parity == EVENPARITY) + { + value_ = even; + } + else if (storage.Parity == ODDPARITY) + { + value_ = odd; + } + else + { + value_ = none; + } +#else + if (storage.c_cflag & PARENB) + { + if (storage.c_cflag & PARODD) + { + value_ = odd; + } + else + { + value_ = even; + } + } + else + { + value_ = none; + } +#endif + ec = asio::error_code(); + return ec; +} + +inline serial_port_base::stop_bits::stop_bits( + serial_port_base::stop_bits::type t) + : value_(t) +{ + if (t != one && t != onepointfive && t != two) + throw std::out_of_range("invalid stop_bits value"); +} + +inline serial_port_base::stop_bits::type +serial_port_base::stop_bits::value() const +{ + return value_; +} + +inline asio::error_code serial_port_base::stop_bits::store( + ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + switch (value_) + { + case one: + storage.StopBits = ONESTOPBIT; + break; + case onepointfive: + storage.StopBits = ONE5STOPBITS; + break; + case two: + storage.StopBits = TWOSTOPBITS; + break; + default: + break; + } +#else + switch (value_) + { + case one: + storage.c_cflag &= ~CSTOPB; + break; + case two: + storage.c_cflag |= CSTOPB; + break; + default: + ec = asio::error::operation_not_supported; + return ec; + } +#endif + ec = asio::error_code(); + return ec; +} + +inline asio::error_code serial_port_base::stop_bits::load( + const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + if (storage.StopBits == ONESTOPBIT) + { + value_ = one; + } + else if (storage.StopBits == ONE5STOPBITS) + { + value_ = onepointfive; + } + else if (storage.StopBits == TWOSTOPBITS) + { + value_ = two; + } + else + { + value_ = one; + } +#else + value_ = (storage.c_cflag & CSTOPB) ? two : one; +#endif + ec = asio::error_code(); + return ec; +} + +inline serial_port_base::character_size::character_size(unsigned int t) + : value_(t) +{ + if (t < 5 || t > 8) + throw std::out_of_range("invalid character_size value"); +} + +inline unsigned int serial_port_base::character_size::value() const +{ + return value_; +} + +inline asio::error_code serial_port_base::character_size::store( + ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + storage.ByteSize = value_; +#else + storage.c_cflag &= ~CSIZE; + switch (value_) + { + case 5: storage.c_cflag |= CS5; break; + case 6: storage.c_cflag |= CS6; break; + case 7: storage.c_cflag |= CS7; break; + case 8: storage.c_cflag |= CS8; break; + default: break; + } +#endif + ec = asio::error_code(); + return ec; +} + +inline asio::error_code serial_port_base::character_size::load( + const ASIO_OPTION_STORAGE& storage, asio::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + value_ = storage.ByteSize; +#else + if ((storage.c_cflag & CSIZE) == CS5) { value_ = 5; } + else if ((storage.c_cflag & CSIZE) == CS6) { value_ = 6; } + else if ((storage.c_cflag & CSIZE) == CS7) { value_ = 7; } + else if ((storage.c_cflag & CSIZE) == CS8) { value_ = 8; } + else + { + // Hmmm, use 8 for now. + value_ = 8; + } +#endif + ec = asio::error_code(); + return ec; +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_SERIAL_PORT_BASE_IPP diff --git a/libtorrent/include/libtorrent/asio/impl/write.ipp b/libtorrent/include/asio/impl/write.ipp similarity index 100% rename from libtorrent/include/libtorrent/asio/impl/write.ipp rename to libtorrent/include/asio/impl/write.ipp diff --git a/libtorrent/include/asio/impl/write_at.ipp b/libtorrent/include/asio/impl/write_at.ipp new file mode 100644 index 000000000..c6fa3078c --- /dev/null +++ b/libtorrent/include/asio/impl/write_at.ipp @@ -0,0 +1,296 @@ +// +// write_at.ipp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_WRITE_AT_IPP +#define ASIO_WRITE_AT_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/buffer.hpp" +#include "asio/completion_condition.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/consuming_buffers.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/detail/throw_error.hpp" + +namespace asio { + +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, asio::error_code& ec) +{ + asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> tmp(buffers); + std::size_t total_transferred = 0; + while (tmp.begin() != tmp.end()) + { + std::size_t bytes_transferred = d.write_some_at( + offset + total_transferred, tmp, ec); + tmp.consume(bytes_transferred); + total_transferred += bytes_transferred; + if (completion_condition(ec, total_transferred)) + return total_transferred; + } + ec = asio::error_code(); + return total_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers) +{ + asio::error_code ec; + std::size_t bytes_transferred = write_at( + d, offset, buffers, transfer_all(), ec); + asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition) +{ + asio::error_code ec; + std::size_t bytes_transferred = write_at( + d, offset, buffers, completion_condition, ec); + asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, asio::basic_streambuf& b, + CompletionCondition completion_condition, asio::error_code& ec) +{ + std::size_t bytes_transferred = write_at( + d, offset, b.data(), completion_condition, ec); + b.consume(bytes_transferred); + return bytes_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, asio::basic_streambuf& b) +{ + asio::error_code ec; + std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec); + asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, asio::basic_streambuf& b, + CompletionCondition completion_condition) +{ + asio::error_code ec; + std::size_t bytes_transferred = write_at( + d, offset, b, completion_condition, ec); + asio::detail::throw_error(ec); + return bytes_transferred; +} + +namespace detail +{ + template + class write_at_handler + { + public: + typedef asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> buffers_type; + + write_at_handler(AsyncRandomAccessWriteDevice& stream, + boost::uint64_t offset, const buffers_type& buffers, + CompletionCondition completion_condition, WriteHandler handler) + : stream_(stream), + buffers_(buffers), + offset_(offset), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + buffers_.consume(bytes_transferred); + if (completion_condition_(ec, total_transferred_) + || buffers_.begin() == buffers_.end()) + { + handler_(ec, total_transferred_); + } + else + { + stream_.async_write_some_at( + offset_ + total_transferred_, buffers_, *this); + } + } + + //private: + AsyncRandomAccessWriteDevice& stream_; + buffers_type buffers_; + boost::uint64_t offset_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + WriteHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + write_at_handler* this_handler) + { + return asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + write_at_handler* this_handler) + { + asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + write_at_handler* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, WriteHandler handler) +{ + asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> tmp(buffers); + d.async_write_some_at(offset, tmp, + detail::write_at_handler( + d, offset, tmp, completion_condition, handler)); +} + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + WriteHandler handler) +{ + async_write_at(d, offset, buffers, transfer_all(), handler); +} + +namespace detail +{ + template + class write_at_streambuf_handler + { + public: + write_at_streambuf_handler( + asio::basic_streambuf& streambuf, + WriteHandler handler) + : streambuf_(streambuf), + handler_(handler) + { + } + + void operator()(const asio::error_code& ec, + std::size_t bytes_transferred) + { + streambuf_.consume(bytes_transferred); + handler_(ec, bytes_transferred); + } + + //private: + asio::basic_streambuf& streambuf_; + WriteHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + write_at_streambuf_handler* this_handler) + { + return asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + write_at_streambuf_handler* this_handler) + { + asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + write_at_streambuf_handler* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, asio::basic_streambuf& b, + CompletionCondition completion_condition, WriteHandler handler) +{ + async_write_at(d, offset, b.data(), completion_condition, + detail::write_at_streambuf_handler< + AsyncRandomAccessWriteDevice, Allocator, WriteHandler>(b, handler)); +} + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, asio::basic_streambuf& b, + WriteHandler handler) +{ + async_write_at(d, offset, b, transfer_all(), handler); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_WRITE_AT_IPP diff --git a/libtorrent/include/libtorrent/asio/io_service.hpp b/libtorrent/include/asio/io_service.hpp similarity index 92% rename from libtorrent/include/libtorrent/asio/io_service.hpp rename to libtorrent/include/asio/io_service.hpp index 451b65a33..b6a34fdc4 100644 --- a/libtorrent/include/libtorrent/asio/io_service.hpp +++ b/libtorrent/include/asio/io_service.hpp @@ -100,6 +100,32 @@ template bool has_service(io_service& ios); * } * } * @endcode + * + * @par Stopping the io_service from running out of work + * + * Some applications may need to prevent an io_service's run() call from + * returning when there is no more work to do. For example, the io_service may + * be being run in a background thread that is launched prior to the + * application's asynchronous operations. The run() call may be kept running by + * creating an object of type asio::io_service::work: + * + * @code asio::io_service io_service; + * asio::io_service::work work(io_service); + * ... @endcode + * + * To effect a shutdown, the application will then need to call the io_service's + * stop() member function. This will cause the io_service run() call to return + * as soon as possible, abandoning unfinished operations and without permitting + * ready handlers to be dispatched. + * + * Alternatively, if the application requires that all operations and handlers + * be allowed to finish normally, the work object may be explicitly destroyed. + * + * @code asio::io_service io_service; + * auto_ptr work( + * new asio::io_service::work(io_service)); + * ... + * work.reset(); // Allow run() to exit. @endcode */ class io_service : private noncopyable @@ -159,6 +185,9 @@ public: * @return The number of handlers that were executed. * * @throws asio::system_error Thrown on failure. + * + * @note The poll() function may also be used to dispatch ready handlers, + * but without blocking. */ std::size_t run(); @@ -178,6 +207,9 @@ public: * @param ec Set to indicate what error occurred, if any. * * @return The number of handlers that were executed. + * + * @note The poll() function may also be used to dispatch ready handlers, + * but without blocking. */ std::size_t run(asio::error_code& ec); diff --git a/libtorrent/include/libtorrent/asio/ip/address.hpp b/libtorrent/include/asio/ip/address.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/address.hpp rename to libtorrent/include/asio/ip/address.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/address_v4.hpp b/libtorrent/include/asio/ip/address_v4.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/address_v4.hpp rename to libtorrent/include/asio/ip/address_v4.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/address_v6.hpp b/libtorrent/include/asio/ip/address_v6.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/address_v6.hpp rename to libtorrent/include/asio/ip/address_v6.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/basic_endpoint.hpp b/libtorrent/include/asio/ip/basic_endpoint.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/basic_endpoint.hpp rename to libtorrent/include/asio/ip/basic_endpoint.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/basic_resolver.hpp b/libtorrent/include/asio/ip/basic_resolver.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/basic_resolver.hpp rename to libtorrent/include/asio/ip/basic_resolver.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/basic_resolver_entry.hpp b/libtorrent/include/asio/ip/basic_resolver_entry.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/basic_resolver_entry.hpp rename to libtorrent/include/asio/ip/basic_resolver_entry.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/basic_resolver_iterator.hpp b/libtorrent/include/asio/ip/basic_resolver_iterator.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/basic_resolver_iterator.hpp rename to libtorrent/include/asio/ip/basic_resolver_iterator.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/basic_resolver_query.hpp b/libtorrent/include/asio/ip/basic_resolver_query.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/basic_resolver_query.hpp rename to libtorrent/include/asio/ip/basic_resolver_query.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/detail/socket_option.hpp b/libtorrent/include/asio/ip/detail/socket_option.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/detail/socket_option.hpp rename to libtorrent/include/asio/ip/detail/socket_option.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/host_name.hpp b/libtorrent/include/asio/ip/host_name.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/host_name.hpp rename to libtorrent/include/asio/ip/host_name.hpp diff --git a/libtorrent/include/asio/ip/icmp.hpp b/libtorrent/include/asio/ip/icmp.hpp new file mode 100644 index 000000000..c36ed2785 --- /dev/null +++ b/libtorrent/include/asio/ip/icmp.hpp @@ -0,0 +1,118 @@ +// +// icmp.hpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_ICMP_HPP +#define ASIO_IP_ICMP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/basic_raw_socket.hpp" +#include "asio/ip/basic_endpoint.hpp" +#include "asio/ip/basic_resolver.hpp" +#include "asio/ip/basic_resolver_iterator.hpp" +#include "asio/ip/basic_resolver_query.hpp" +#include "asio/detail/socket_types.hpp" + +namespace asio { +namespace ip { + +/// Encapsulates the flags needed for ICMP. +/** + * The asio::ip::icmp class contains flags necessary for ICMP sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol, InternetProtocol. + */ +class icmp +{ +public: + /// The type of a ICMP endpoint. + typedef basic_endpoint endpoint; + + /// The type of a resolver query. + typedef basic_resolver_query resolver_query; + + /// The type of a resolver iterator. + typedef basic_resolver_iterator resolver_iterator; + + /// Construct to represent the IPv4 ICMP protocol. + static icmp v4() + { + return icmp(IPPROTO_ICMP, PF_INET); + } + + /// Construct to represent the IPv6 ICMP protocol. + static icmp v6() + { + return icmp(IPPROTO_ICMPV6, PF_INET6); + } + + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_RAW; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return protocol_; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return family_; + } + + /// The ICMP socket type. + typedef basic_raw_socket socket; + + /// The ICMP resolver type. + typedef basic_resolver resolver; + + /// Compare two protocols for equality. + friend bool operator==(const icmp& p1, const icmp& p2) + { + return p1.protocol_ == p2.protocol_ && p1.family_ == p2.family_; + } + + /// Compare two protocols for inequality. + friend bool operator!=(const icmp& p1, const icmp& p2) + { + return p1.protocol_ != p2.protocol_ || p1.family_ != p2.family_; + } + +private: + // Construct with a specific family. + explicit icmp(int protocol, int family) + : protocol_(protocol), + family_(family) + { + } + + int protocol_; + int family_; +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_ICMP_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/multicast.hpp b/libtorrent/include/asio/ip/multicast.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/multicast.hpp rename to libtorrent/include/asio/ip/multicast.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/resolver_query_base.hpp b/libtorrent/include/asio/ip/resolver_query_base.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/resolver_query_base.hpp rename to libtorrent/include/asio/ip/resolver_query_base.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/resolver_service.hpp b/libtorrent/include/asio/ip/resolver_service.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/resolver_service.hpp rename to libtorrent/include/asio/ip/resolver_service.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/tcp.hpp b/libtorrent/include/asio/ip/tcp.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/tcp.hpp rename to libtorrent/include/asio/ip/tcp.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/udp.hpp b/libtorrent/include/asio/ip/udp.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/udp.hpp rename to libtorrent/include/asio/ip/udp.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/unicast.hpp b/libtorrent/include/asio/ip/unicast.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/unicast.hpp rename to libtorrent/include/asio/ip/unicast.hpp diff --git a/libtorrent/include/libtorrent/asio/ip/v6_only.hpp b/libtorrent/include/asio/ip/v6_only.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ip/v6_only.hpp rename to libtorrent/include/asio/ip/v6_only.hpp diff --git a/libtorrent/include/libtorrent/asio/is_read_buffered.hpp b/libtorrent/include/asio/is_read_buffered.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/is_read_buffered.hpp rename to libtorrent/include/asio/is_read_buffered.hpp diff --git a/libtorrent/include/libtorrent/asio/is_write_buffered.hpp b/libtorrent/include/asio/is_write_buffered.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/is_write_buffered.hpp rename to libtorrent/include/asio/is_write_buffered.hpp diff --git a/libtorrent/include/asio/local/basic_endpoint.hpp b/libtorrent/include/asio/local/basic_endpoint.hpp new file mode 100644 index 000000000..75dd092e3 --- /dev/null +++ b/libtorrent/include/asio/local/basic_endpoint.hpp @@ -0,0 +1,265 @@ +// +// basic_endpoint.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Derived from a public domain implementation written by Daniel Casimiro. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_LOCAL_BASIC_ENDPOINT_HPP +#define ASIO_LOCAL_BASIC_ENDPOINT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/error.hpp" +#include "asio/system_error.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/detail/throw_error.hpp" + +#if !defined(ASIO_DISABLE_LOCAL_SOCKETS) +# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# define ASIO_HAS_LOCAL_SOCKETS 1 +# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(ASIO_DISABLE_LOCAL_SOCKETS) + +#if defined(ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + + +namespace asio { +namespace local { + +/// Describes an endpoint for a UNIX socket. +/** + * The asio::local::basic_endpoint class template describes an endpoint + * that may be associated with a particular UNIX socket. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * Endpoint. + */ +template +class basic_endpoint +{ +public: + /// The protocol type associated with the endpoint. + typedef Protocol protocol_type; + + /// The type of the endpoint structure. This type is dependent on the + /// underlying implementation of the socket layer. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined data_type; +#else + typedef asio::detail::socket_addr_type data_type; +#endif + + /// Default constructor. + basic_endpoint() + { + init("", 0); + } + + /// Construct an endpoint using the specified path name. + basic_endpoint(const char* path) + { + using namespace std; // For strlen. + init(path, strlen(path)); + } + + /// Construct an endpoint using the specified path name. + basic_endpoint(const std::string& path) + { + init(path.data(), path.length()); + } + + /// Copy constructor. + basic_endpoint(const basic_endpoint& other) + : data_(other.data_), + path_length_(other.path_length_) + { + } + + /// Assign from another endpoint. + basic_endpoint& operator=(const basic_endpoint& other) + { + data_ = other.data_; + path_length_ = other.path_length_; + return *this; + } + + /// The protocol associated with the endpoint. + protocol_type protocol() const + { + return protocol_type(); + } + + /// Get the underlying endpoint in the native type. + data_type* data() + { + return &data_.base; + } + + /// Get the underlying endpoint in the native type. + const data_type* data() const + { + return &data_.base; + } + + /// Get the underlying size of the endpoint in the native type. + std::size_t size() const + { + return path_length_ + + offsetof(asio::detail::sockaddr_un_type, sun_path); + } + + /// Set the underlying size of the endpoint in the native type. + void resize(std::size_t size) + { + if (size > sizeof(asio::detail::sockaddr_un_type)) + { + asio::system_error e(asio::error::invalid_argument); + boost::throw_exception(e); + } + else if (size == 0) + { + path_length_ = 0; + } + else + { + path_length_ = size + - offsetof(asio::detail::sockaddr_un_type, sun_path); + + // The path returned by the operating system may be NUL-terminated. + if (path_length_ > 0 && data_.local.sun_path[path_length_] == 0) + --path_length_; + } + } + + /// Get the capacity of the endpoint in the native type. + std::size_t capacity() const + { + return sizeof(asio::detail::sockaddr_un_type); + } + + /// Get the path associated with the endpoint. + std::string path() const + { + return std::string(data_.local.sun_path, path_length_); + } + + /// Set the path associated with the endpoint. + void path(const char* p) + { + using namespace std; // For strlen. + init(p, strlen(p)); + } + + /// Set the path associated with the endpoint. + void path(const std::string& p) + { + init(p.data(), p.length()); + } + + /// Compare two endpoints for equality. + friend bool operator==(const basic_endpoint& e1, + const basic_endpoint& e2) + { + return e1.path() == e2.path(); + } + + /// Compare two endpoints for inequality. + friend bool operator!=(const basic_endpoint& e1, + const basic_endpoint& e2) + { + return e1.path() != e2.path(); + } + + /// Compare endpoints for ordering. + friend bool operator<(const basic_endpoint& e1, + const basic_endpoint& e2) + { + return e1.path() < e2.path(); + } + +private: + // The underlying UNIX socket address. + union data_union + { + asio::detail::socket_addr_type base; + asio::detail::sockaddr_un_type local; + } data_; + + // The length of the path associated with the endpoint. + std::size_t path_length_; + + // Initialise with a specified path. + void init(const char* path, std::size_t path_length) + { + if (path_length > sizeof(data_.local.sun_path) - 1) + { + // The buffer is not large enough to store this address. + asio::error_code ec(asio::error::name_too_long); + asio::detail::throw_error(ec); + } + + using namespace std; // For memcpy. + data_.local = asio::detail::sockaddr_un_type(); + data_.local.sun_family = AF_UNIX; + memcpy(data_.local.sun_path, path, path_length); + path_length_ = path_length; + + // NUL-terminate normal path names. Names that start with a NUL are in the + // UNIX domain protocol's "abstract namespace" and are not NUL-terminated. + if (path_length > 0 && data_.local.sun_path[0] == 0) + data_.local.sun_path[path_length] = 0; + } +}; + +/// Output an endpoint as a string. +/** + * Used to output a human-readable string for a specified endpoint. + * + * @param os The output stream to which the string will be written. + * + * @param endpoint The endpoint to be written. + * + * @return The output stream. + * + * @relates asio::local::basic_endpoint + */ +template +std::basic_ostream& operator<<( + std::basic_ostream& os, + const basic_endpoint& endpoint) +{ + os << endpoint.path(); + return os; +} + +} // namespace local +} // namespace asio + +#endif // defined(ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_LOCAL_BASIC_ENDPOINT_HPP diff --git a/libtorrent/include/asio/local/connect_pair.hpp b/libtorrent/include/asio/local/connect_pair.hpp new file mode 100644 index 000000000..e4f73f91b --- /dev/null +++ b/libtorrent/include/asio/local/connect_pair.hpp @@ -0,0 +1,100 @@ +// +// connect_pair.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_LOCAL_CONNECT_PAIR_HPP +#define ASIO_LOCAL_CONNECT_PAIR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/basic_socket.hpp" +#include "asio/error.hpp" +#include "asio/local/basic_endpoint.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/throw_error.hpp" + +#if defined(ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace local { + +/// Create a pair of connected sockets. +template +void connect_pair( + basic_socket& socket1, + basic_socket& socket2); + +/// Create a pair of connected sockets. +template +asio::error_code connect_pair( + basic_socket& socket1, + basic_socket& socket2, + asio::error_code& ec); + +template +inline void connect_pair( + basic_socket& socket1, + basic_socket& socket2) +{ + asio::error_code ec; + connect_pair(socket1, socket2, ec); + asio::detail::throw_error(ec); +} + +template +inline asio::error_code connect_pair( + basic_socket& socket1, + basic_socket& socket2, + asio::error_code& ec) +{ + // Check that this function is only being used with a UNIX domain socket. + asio::local::basic_endpoint* tmp + = static_cast(0); + (void)tmp; + + Protocol protocol; + asio::detail::socket_type sv[2]; + if (asio::detail::socket_ops::socketpair(protocol.family(), + protocol.type(), protocol.protocol(), sv, ec) + == asio::detail::socket_error_retval) + return ec; + + if (socket1.assign(protocol, sv[0], ec)) + { + asio::error_code temp_ec; + asio::detail::socket_ops::close(sv[0], temp_ec); + asio::detail::socket_ops::close(sv[1], temp_ec); + return ec; + } + + if (socket2.assign(protocol, sv[1], ec)) + { + asio::error_code temp_ec; + socket1.close(temp_ec); + asio::detail::socket_ops::close(sv[1], temp_ec); + return ec; + } + + return ec; +} + +} // namespace local +} // namespace asio + +#endif // defined(ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_LOCAL_CONNECT_PAIR_HPP diff --git a/libtorrent/include/asio/local/datagram_protocol.hpp b/libtorrent/include/asio/local/datagram_protocol.hpp new file mode 100644 index 000000000..c7adacfc9 --- /dev/null +++ b/libtorrent/include/asio/local/datagram_protocol.hpp @@ -0,0 +1,78 @@ +// +// datagram_protocol.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP +#define ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/basic_datagram_socket.hpp" +#include "asio/local/basic_endpoint.hpp" +#include "asio/detail/socket_types.hpp" + +#if defined(ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace local { + +/// Encapsulates the flags needed for datagram-oriented UNIX sockets. +/** + * The asio::local::datagram_protocol class contains flags necessary for + * datagram-oriented UNIX domain sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol. + */ +class datagram_protocol +{ +public: + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_DGRAM; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return 0; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return AF_UNIX; + } + + /// The type of a UNIX domain endpoint. + typedef basic_endpoint endpoint; + + /// The UNIX domain socket type. + typedef basic_datagram_socket socket; +}; + +} // namespace local +} // namespace asio + +#endif // defined(ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP diff --git a/libtorrent/include/asio/local/stream_protocol.hpp b/libtorrent/include/asio/local/stream_protocol.hpp new file mode 100644 index 000000000..91813e8e0 --- /dev/null +++ b/libtorrent/include/asio/local/stream_protocol.hpp @@ -0,0 +1,86 @@ +// +// stream_protocol.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_LOCAL_STREAM_PROTOCOL_HPP +#define ASIO_LOCAL_STREAM_PROTOCOL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/basic_socket_acceptor.hpp" +#include "asio/basic_socket_iostream.hpp" +#include "asio/basic_stream_socket.hpp" +#include "asio/local/basic_endpoint.hpp" +#include "asio/detail/socket_types.hpp" + +#if defined(ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace local { + +/// Encapsulates the flags needed for stream-oriented UNIX sockets. +/** + * The asio::local::stream_protocol class contains flags necessary for + * stream-oriented UNIX domain sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol. + */ +class stream_protocol +{ +public: + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_STREAM; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return 0; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return AF_UNIX; + } + + /// The type of a UNIX domain endpoint. + typedef basic_endpoint endpoint; + + /// The UNIX domain socket type. + typedef basic_stream_socket socket; + + /// The UNIX domain acceptor type. + typedef basic_socket_acceptor acceptor; + + /// The UNIX domain iostream type. + typedef basic_socket_iostream iostream; +}; + +} // namespace local +} // namespace asio + +#endif // defined(ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_LOCAL_STREAM_PROTOCOL_HPP diff --git a/libtorrent/include/libtorrent/asio/placeholders.hpp b/libtorrent/include/asio/placeholders.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/placeholders.hpp rename to libtorrent/include/asio/placeholders.hpp diff --git a/libtorrent/include/asio/posix/basic_descriptor.hpp b/libtorrent/include/asio/posix/basic_descriptor.hpp new file mode 100644 index 000000000..241a3e315 --- /dev/null +++ b/libtorrent/include/asio/posix/basic_descriptor.hpp @@ -0,0 +1,280 @@ +// +// basic_descriptor.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_POSIX_BASIC_DESCRIPTOR_HPP +#define ASIO_POSIX_BASIC_DESCRIPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/basic_io_object.hpp" +#include "asio/error.hpp" +#include "asio/posix/descriptor_base.hpp" +#include "asio/detail/throw_error.hpp" + +namespace asio { +namespace posix { + +/// Provides POSIX descriptor functionality. +/** + * The posix::basic_descriptor class template provides the ability to wrap a + * POSIX descriptor. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_descriptor + : public basic_io_object, + public descriptor_base +{ +public: + /// The native representation of a descriptor. + typedef typename DescriptorService::native_type native_type; + + /// A basic_descriptor is always the lowest layer. + typedef basic_descriptor lowest_layer_type; + + /// Construct a basic_descriptor without opening it. + /** + * This constructor creates a descriptor without opening it. + * + * @param io_service The io_service object that the descriptor will use to + * dispatch handlers for any asynchronous operations performed on the + * descriptor. + */ + explicit basic_descriptor(asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Construct a basic_descriptor on an existing native descriptor. + /** + * This constructor creates a descriptor object to hold an existing native + * descriptor. + * + * @param io_service The io_service object that the descriptor will use to + * dispatch handlers for any asynchronous operations performed on the + * descriptor. + * + * @param native_descriptor A native descriptor. + * + * @throws asio::system_error Thrown on failure. + */ + basic_descriptor(asio::io_service& io_service, + const native_type& native_descriptor) + : basic_io_object(io_service) + { + asio::error_code ec; + this->service.assign(this->implementation, native_descriptor, ec); + asio::detail::throw_error(ec); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_descriptor cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Assign an existing native descriptor to the descriptor. + /* + * This function opens the descriptor to hold an existing native descriptor. + * + * @param native_descriptor A native descriptor. + * + * @throws asio::system_error Thrown on failure. + */ + void assign(const native_type& native_descriptor) + { + asio::error_code ec; + this->service.assign(this->implementation, native_descriptor, ec); + asio::detail::throw_error(ec); + } + + /// Assign an existing native descriptor to the descriptor. + /* + * This function opens the descriptor to hold an existing native descriptor. + * + * @param native_descriptor A native descriptor. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code assign(const native_type& native_descriptor, + asio::error_code& ec) + { + return this->service.assign(this->implementation, native_descriptor, ec); + } + + /// Determine whether the descriptor is open. + bool is_open() const + { + return this->service.is_open(this->implementation); + } + + /// Close the descriptor. + /** + * This function is used to close the descriptor. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + */ + void close() + { + asio::error_code ec; + this->service.close(this->implementation, ec); + asio::detail::throw_error(ec); + } + + /// Close the descriptor. + /** + * This function is used to close the descriptor. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code close(asio::error_code& ec) + { + return this->service.close(this->implementation, ec); + } + + /// Get the native descriptor representation. + /** + * This function may be used to obtain the underlying representation of the + * descriptor. This is intended to allow access to native descriptor + * functionality that is not otherwise provided. + */ + native_type native() + { + return this->service.native(this->implementation); + } + + /// Cancel all asynchronous operations associated with the descriptor. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + */ + void cancel() + { + asio::error_code ec; + this->service.cancel(this->implementation, ec); + asio::detail::throw_error(ec); + } + + /// Cancel all asynchronous operations associated with the descriptor. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code cancel(asio::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Perform an IO control command on the descriptor. + /** + * This function is used to execute an IO control command on the descriptor. + * + * @param command The IO control command to be performed on the descriptor. + * + * @throws asio::system_error Thrown on failure. + * + * @sa IoControlCommand @n + * asio::posix::descriptor_base::bytes_readable @n + * asio::posix::descriptor_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * asio::posix::stream_descriptor descriptor(io_service); + * ... + * asio::posix::stream_descriptor::bytes_readable command; + * descriptor.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + void io_control(IoControlCommand& command) + { + asio::error_code ec; + this->service.io_control(this->implementation, command, ec); + asio::detail::throw_error(ec); + } + + /// Perform an IO control command on the descriptor. + /** + * This function is used to execute an IO control command on the descriptor. + * + * @param command The IO control command to be performed on the descriptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa IoControlCommand @n + * asio::posix::descriptor_base::bytes_readable @n + * asio::posix::descriptor_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * asio::posix::stream_descriptor descriptor(io_service); + * ... + * asio::posix::stream_descriptor::bytes_readable command; + * asio::error_code ec; + * descriptor.io_control(command, ec); + * if (ec) + * { + * // An error occurred. + * } + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + asio::error_code io_control(IoControlCommand& command, + asio::error_code& ec) + { + return this->service.io_control(this->implementation, command, ec); + } + +protected: + /// Protected destructor to prevent deletion through this type. + ~basic_descriptor() + { + } +}; + +} // namespace posix +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_POSIX_BASIC_DESCRIPTOR_HPP diff --git a/libtorrent/include/asio/posix/basic_stream_descriptor.hpp b/libtorrent/include/asio/posix/basic_stream_descriptor.hpp new file mode 100644 index 000000000..62185eaa0 --- /dev/null +++ b/libtorrent/include/asio/posix/basic_stream_descriptor.hpp @@ -0,0 +1,304 @@ +// +// basic_stream_descriptor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP +#define ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/error.hpp" +#include "asio/posix/basic_descriptor.hpp" +#include "asio/posix/stream_descriptor_service.hpp" +#include "asio/detail/throw_error.hpp" + +#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace posix { + +/// Provides stream-oriented descriptor functionality. +/** + * The posix::basic_stream_descriptor class template provides asynchronous and + * blocking stream-oriented descriptor functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template +class basic_stream_descriptor + : public basic_descriptor +{ +public: + /// The native representation of a descriptor. + typedef typename StreamDescriptorService::native_type native_type; + + /// Construct a basic_stream_descriptor without opening it. + /** + * This constructor creates a stream descriptor without opening it. The + * descriptor needs to be opened and then connected or accepted before data + * can be sent or received on it. + * + * @param io_service The io_service object that the stream descriptor will + * use to dispatch handlers for any asynchronous operations performed on the + * descriptor. + */ + explicit basic_stream_descriptor(asio::io_service& io_service) + : basic_descriptor(io_service) + { + } + + /// Construct a basic_stream_descriptor on an existing native descriptor. + /** + * This constructor creates a stream descriptor object to hold an existing + * native descriptor. + * + * @param io_service The io_service object that the stream descriptor will + * use to dispatch handlers for any asynchronous operations performed on the + * descriptor. + * + * @param native_descriptor The new underlying descriptor implementation. + * + * @throws asio::system_error Thrown on failure. + */ + basic_stream_descriptor(asio::io_service& io_service, + const native_type& native_descriptor) + : basic_descriptor(io_service, native_descriptor) + { + } + + /// Write some data to the descriptor. + /** + * This function is used to write data to the stream descriptor. The function + * call will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the descriptor. + * + * @returns The number of bytes written. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.write_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->service.write_some(this->implementation, buffers, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the descriptor. + /** + * This function is used to write data to the stream descriptor. The function + * call will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the descriptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + asio::error_code& ec) + { + return this->service.write_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the stream + * descriptor. The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the descriptor. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.async_write_some(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + this->service.async_write_some(this->implementation, buffers, handler); + } + + /// Read some data from the descriptor. + /** + * This function is used to read data from the stream descriptor. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.read_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->service.read_some(this->implementation, buffers, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the descriptor. + /** + * This function is used to read data from the stream descriptor. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + asio::error_code& ec) + { + return this->service.read_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the stream + * descriptor. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.async_read_some(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + this->service.async_read_some(this->implementation, buffers, handler); + } +}; + +} // namespace posix +} // namespace asio + +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP diff --git a/libtorrent/include/asio/posix/descriptor_base.hpp b/libtorrent/include/asio/posix/descriptor_base.hpp new file mode 100644 index 000000000..6ea2738df --- /dev/null +++ b/libtorrent/include/asio/posix/descriptor_base.hpp @@ -0,0 +1,93 @@ +// +// descriptor_base.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_POSIX_DESCRIPTOR_BASE_HPP +#define ASIO_POSIX_DESCRIPTOR_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/detail/io_control.hpp" +#include "asio/detail/socket_option.hpp" + +namespace asio { +namespace posix { + +/// The descriptor_base class is used as a base for the basic_stream_descriptor +/// class template so that we have a common place to define the associated +/// IO control commands. +class descriptor_base +{ +public: + /// IO control command to set the blocking mode of the descriptor. + /** + * Implements the FIONBIO IO control command. + * + * @par Example + * @code + * asio::posix::stream_descriptor descriptor(io_service); + * ... + * asio::descriptor_base::non_blocking_io command(true); + * descriptor.io_control(command); + * @endcode + * + * @par Concepts: + * IoControlCommand. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined non_blocking_io; +#else + typedef asio::detail::io_control::non_blocking_io non_blocking_io; +#endif + + /// IO control command to get the amount of data that can be read without + /// blocking. + /** + * Implements the FIONREAD IO control command. + * + * @par Example + * @code + * asio::posix::stream_descriptor descriptor(io_service); + * ... + * asio::descriptor_base::bytes_readable command(true); + * descriptor.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + * + * @par Concepts: + * IoControlCommand. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined bytes_readable; +#else + typedef asio::detail::io_control::bytes_readable bytes_readable; +#endif + +protected: + /// Protected destructor to prevent deletion through this type. + ~descriptor_base() + { + } +}; + +} // namespace posix +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_POSIX_DESCRIPTOR_BASE_HPP diff --git a/libtorrent/include/asio/posix/stream_descriptor.hpp b/libtorrent/include/asio/posix/stream_descriptor.hpp new file mode 100644 index 000000000..ccf697726 --- /dev/null +++ b/libtorrent/include/asio/posix/stream_descriptor.hpp @@ -0,0 +1,39 @@ +// +// stream_descriptor.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_POSIX_STREAM_DESCRIPTOR_HPP +#define ASIO_POSIX_STREAM_DESCRIPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/posix/basic_stream_descriptor.hpp" + +#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace posix { + +/// Typedef for the typical usage of a stream-oriented descriptor. +typedef basic_stream_descriptor<> stream_descriptor; + +} // namespace posix +} // namespace asio + +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_POSIX_STREAM_DESCRIPTOR_HPP diff --git a/libtorrent/include/asio/posix/stream_descriptor_service.hpp b/libtorrent/include/asio/posix/stream_descriptor_service.hpp new file mode 100644 index 000000000..df8ccbfcb --- /dev/null +++ b/libtorrent/include/asio/posix/stream_descriptor_service.hpp @@ -0,0 +1,200 @@ +// +// stream_descriptor_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP +#define ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/epoll_reactor.hpp" +#include "asio/detail/kqueue_reactor.hpp" +#include "asio/detail/select_reactor.hpp" +#include "asio/detail/service_base.hpp" +#include "asio/detail/reactive_descriptor_service.hpp" + +#if !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) +# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# define ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1 +# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) + +#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace posix { + +/// Default service implementation for a stream descriptor. +class stream_descriptor_service +#if defined(GENERATING_DOCUMENTATION) + : public asio::io_service::service +#else + : public asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. +#if defined(ASIO_HAS_EPOLL) + typedef detail::reactive_descriptor_service< + detail::epoll_reactor > service_impl_type; +#elif defined(ASIO_HAS_KQUEUE) + typedef detail::reactive_descriptor_service< + detail::kqueue_reactor > service_impl_type; +#elif defined(ASIO_HAS_DEV_POLL) + typedef detail::reactive_descriptor_service< + detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_descriptor_service< + detail::select_reactor > service_impl_type; +#endif + +public: + /// The type of a stream descriptor implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native descriptor type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new stream descriptor service for the specified io_service. + explicit stream_descriptor_service(asio::io_service& io_service) + : asio::detail::service_base(io_service), + service_impl_(asio::use_service(io_service)) + { + } + + /// Destroy all user-defined descriptorr objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new stream descriptor implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a stream descriptor implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Assign an existing native descriptor to a stream descriptor. + asio::error_code assign(implementation_type& impl, + const native_type& native_descriptor, asio::error_code& ec) + { + return service_impl_.assign(impl, native_descriptor, ec); + } + + /// Determine whether the descriptor is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a stream descriptor implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native descriptor implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the descriptor. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Perform an IO control command on the descriptor. + template + asio::error_code io_control(implementation_type& impl, + IoControlCommand& command, asio::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Write the given data to the stream. + template + std::size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return service_impl_.write_some(impl, buffers, ec); + } + + /// Start an asynchronous write. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, WriteHandler descriptorr) + { + service_impl_.async_write_some(impl, buffers, descriptorr); + } + + /// Read some data from the stream. + template + std::size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return service_impl_.read_some(impl, buffers, ec); + } + + /// Start an asynchronous read. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, ReadHandler descriptorr) + { + service_impl_.async_read_some(impl, buffers, descriptorr); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace posix +} // namespace asio + +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP diff --git a/libtorrent/include/asio/raw_socket_service.hpp b/libtorrent/include/asio/raw_socket_service.hpp new file mode 100644 index 000000000..c9d251581 --- /dev/null +++ b/libtorrent/include/asio/raw_socket_service.hpp @@ -0,0 +1,323 @@ +// +// raw_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_RAW_SOCKET_SERVICE_HPP +#define ASIO_RAW_SOCKET_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/epoll_reactor.hpp" +#include "asio/detail/kqueue_reactor.hpp" +#include "asio/detail/select_reactor.hpp" +#include "asio/detail/service_base.hpp" +#include "asio/detail/reactive_socket_service.hpp" +#include "asio/detail/win_iocp_socket_service.hpp" + +namespace asio { + +/// Default service implementation for a raw socket. +template +class raw_socket_service +#if defined(GENERATING_DOCUMENTATION) + : public asio::io_service::service +#else + : public asio::detail::service_base > +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static asio::io_service::id id; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + +private: + // The type of the platform-specific implementation. +#if defined(ASIO_HAS_IOCP) + typedef detail::win_iocp_socket_service service_impl_type; +#elif defined(ASIO_HAS_EPOLL) + typedef detail::reactive_socket_service< + Protocol, detail::epoll_reactor > service_impl_type; +#elif defined(ASIO_HAS_KQUEUE) + typedef detail::reactive_socket_service< + Protocol, detail::kqueue_reactor > service_impl_type; +#elif defined(ASIO_HAS_DEV_POLL) + typedef detail::reactive_socket_service< + Protocol, detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_socket_service< + Protocol, detail::select_reactor > service_impl_type; +#endif + +public: + /// The type of a raw socket. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef typename service_impl_type::implementation_type implementation_type; +#endif + + /// The native socket type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef typename service_impl_type::native_type native_type; +#endif + + /// Construct a new raw socket service for the specified io_service. + explicit raw_socket_service(asio::io_service& io_service) + : asio::detail::service_base< + raw_socket_service >(io_service), + service_impl_(asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new raw socket implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a raw socket implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + // Open a new raw socket implementation. + asio::error_code open(implementation_type& impl, + const protocol_type& protocol, asio::error_code& ec) + { + if (protocol.type() == SOCK_RAW) + service_impl_.open(impl, protocol, ec); + else + ec = asio::error::invalid_argument; + return ec; + } + + /// Assign an existing native socket to a raw socket. + asio::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_type& native_socket, + asio::error_code& ec) + { + return service_impl_.assign(impl, protocol, native_socket, ec); + } + + /// Determine whether the socket is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a raw socket implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native socket implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the socket. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + bool at_mark(const implementation_type& impl, + asio::error_code& ec) const + { + return service_impl_.at_mark(impl, ec); + } + + /// Determine the number of bytes available for reading. + std::size_t available(const implementation_type& impl, + asio::error_code& ec) const + { + return service_impl_.available(impl, ec); + } + + // Bind the raw socket to the specified local endpoint. + asio::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, asio::error_code& ec) + { + return service_impl_.bind(impl, endpoint, ec); + } + + /// Connect the raw socket to the specified endpoint. + asio::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, asio::error_code& ec) + { + return service_impl_.connect(impl, peer_endpoint, ec); + } + + /// Start an asynchronous connect. + template + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, ConnectHandler handler) + { + service_impl_.async_connect(impl, peer_endpoint, handler); + } + + /// Set a socket option. + template + asio::error_code set_option(implementation_type& impl, + const SettableSocketOption& option, asio::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a socket option. + template + asio::error_code get_option(const implementation_type& impl, + GettableSocketOption& option, asio::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Perform an IO control command on the socket. + template + asio::error_code io_control(implementation_type& impl, + IoControlCommand& command, asio::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + asio::error_code& ec) const + { + return service_impl_.local_endpoint(impl, ec); + } + + /// Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + asio::error_code& ec) const + { + return service_impl_.remote_endpoint(impl, ec); + } + + /// Disable sends or receives on the socket. + asio::error_code shutdown(implementation_type& impl, + socket_base::shutdown_type what, asio::error_code& ec) + { + return service_impl_.shutdown(impl, what, ec); + } + + /// Send the given data to the peer. + template + std::size_t send(implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + return service_impl_.send(impl, buffers, flags, ec); + } + + /// Start an asynchronous send. + template + void async_send(implementation_type& impl, const ConstBufferSequence& buffers, + socket_base::message_flags flags, WriteHandler handler) + { + service_impl_.async_send(impl, buffers, flags, handler); + } + + /// Send raw data to the specified endpoint. + template + std::size_t send_to(implementation_type& impl, + const ConstBufferSequence& buffers, const endpoint_type& destination, + socket_base::message_flags flags, asio::error_code& ec) + { + return service_impl_.send_to(impl, buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + template + void async_send_to(implementation_type& impl, + const ConstBufferSequence& buffers, const endpoint_type& destination, + socket_base::message_flags flags, WriteHandler handler) + { + service_impl_.async_send_to(impl, buffers, destination, flags, handler); + } + + /// Receive some data from the peer. + template + std::size_t receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + return service_impl_.receive(impl, buffers, flags, ec); + } + + /// Start an asynchronous receive. + template + void async_receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, ReadHandler handler) + { + service_impl_.async_receive(impl, buffers, flags, handler); + } + + /// Receive raw data with the endpoint of the sender. + template + std::size_t receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, asio::error_code& ec) + { + return service_impl_.receive_from(impl, buffers, sender_endpoint, flags, + ec); + } + + /// Start an asynchronous receive that will get the endpoint of the sender. + template + void async_receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, ReadHandler handler) + { + service_impl_.async_receive_from(impl, buffers, sender_endpoint, flags, + handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_RAW_SOCKET_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/read.hpp b/libtorrent/include/asio/read.hpp similarity index 99% rename from libtorrent/include/libtorrent/asio/read.hpp rename to libtorrent/include/asio/read.hpp index 46bca2622..7c0b82247 100644 --- a/libtorrent/include/libtorrent/asio/read.hpp +++ b/libtorrent/include/asio/read.hpp @@ -29,6 +29,9 @@ namespace asio { /** * @defgroup read asio::read + * + * @brief Attempt to read a certain amount of data from a stream before + * returning. */ /*@{*/ @@ -269,6 +272,9 @@ std::size_t read(SyncReadStream& s, basic_streambuf& b, /*@}*/ /** * @defgroup async_read asio::async_read + * + * @brief Start an asynchronous operation to read a certain amount of data from + * a stream. */ /*@{*/ diff --git a/libtorrent/include/asio/read_at.hpp b/libtorrent/include/asio/read_at.hpp new file mode 100644 index 000000000..bcc247a0f --- /dev/null +++ b/libtorrent/include/asio/read_at.hpp @@ -0,0 +1,568 @@ +// +// read_at.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_READ_AT_HPP +#define ASIO_READ_AT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/basic_streambuf.hpp" +#include "asio/error.hpp" + +namespace asio { + +/** + * @defgroup read_at asio::read_at + * + * @brief Attempt to read a certain amount of data at the specified offset + * before returning. + */ +/*@{*/ + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code asio::read_at(d, 42, asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code asio::read_at( + * d, 42, buffers, + * asio::transfer_all()); @endcode + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code asio::read_at(d, 42, asio::buffer(data, size), + * asio::transfer_at_least(32)); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const asio::error_code& error, // Result of latest read_some_at + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, asio::error_code& ec); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + * + * @note This overload is equivalent to calling: + * @code asio::read_at( + * d, 42, b, + * asio::transfer_all()); @endcode + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b, + CompletionCondition completion_condition); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b, + CompletionCondition completion_condition, asio::error_code& ec); + +/*@}*/ +/** + * @defgroup async_read_at asio::async_read_at + * + * @brief Start an asynchronous operation to read a certain amount of data at + * the specified offset. + */ +/*@{*/ + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. Although the buffers object may be copied as necessary, ownership of + * the underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * asio::async_read_at(d, 42, asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code asio::async_read_at( + * d, 42, buffers, + * asio::transfer_all(), + * handler); @endcode + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset, + const MutableBufferSequence& buffers, ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. Although the buffers object may be copied as necessary, ownership of + * the underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's async_read_some_at function are + * required. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code asio::async_read_at(d, 42, + * asio::buffer(data, size), + * asio::transfer_at_least(32), + * handler); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b A basic_streambuf object into which the data will be read. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note This overload is equivalent to calling: + * @code asio::async_read_at( + * d, 42, b, + * asio::transfer_all(), + * handler); @endcode + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset, + basic_streambuf& b, ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * async_read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b A basic_streambuf object into which the data will be read. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's async_read_some_at function are + * required. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b, + CompletionCondition completion_condition, ReadHandler handler); + +/*@}*/ + +} // namespace asio + +#include "asio/impl/read_at.ipp" + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_READ_AT_HPP diff --git a/libtorrent/include/asio/read_until.hpp b/libtorrent/include/asio/read_until.hpp new file mode 100644 index 000000000..69922e266 --- /dev/null +++ b/libtorrent/include/asio/read_until.hpp @@ -0,0 +1,823 @@ +// +// read_until.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_READ_UNTIL_HPP +#define ASIO_READ_UNTIL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include +#include +#include +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/basic_streambuf.hpp" +#include "asio/error.hpp" + +namespace asio { + +namespace detail +{ + template + struct has_result_type + { + struct big { char a[100]; }; + template static big helper(U, ...); + template static char helper(U, typename U::result_type* = 0); + static const T& ref(); + enum { value = (sizeof((helper)((ref)())) == 1) }; + }; +} // namespace detail + +/// Type trait used to determine whether a type can be used as a match condition +/// function with read_until and async_read_until. +template +struct is_match_condition +{ +#if defined(GENERATING_DOCUMENTATION) + /// The value member is true if the type may be used as a match condition. + static const bool value; +#else + enum + { + value = boost::is_function::type>::value + || detail::has_result_type::value + }; +#endif +}; + +/** + * @defgroup read_until asio::read_until + * + * @brief Read data into a streambuf until it contains a delimiter, matches a + * regular expression, or a function object indicates a match. + */ +/*@{*/ + +/// Read data into a streambuf until it contains a specified delimiter. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains the specified delimiter. The call will block + * until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains the + * delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param delim The delimiter character. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the delimiter. + * + * @throws asio::system_error Thrown on failure. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond the delimiter. An application will typically leave + * that data in the streambuf for a subsequent read_until operation to examine. + * + * @par Example + * To read data into a streambuf until a newline is encountered: + * @code asio::streambuf b; + * asio::read_until(s, b, '\n'); + * std::istream is(&b); + * std::string line; + * std::getline(is, line); @endcode + */ +template +std::size_t read_until(SyncReadStream& s, + asio::basic_streambuf& b, char delim); + +/// Read data into a streambuf until it contains a specified delimiter. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains the specified delimiter. The call will block + * until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains the + * delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param delim The delimiter character. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the delimiter. Returns 0 if an error occurred. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond the delimiter. An application will typically leave + * that data in the streambuf for a subsequent read_until operation to examine. + */ +template +std::size_t read_until(SyncReadStream& s, + asio::basic_streambuf& b, char delim, + asio::error_code& ec); + +/// Read data into a streambuf until it contains a specified delimiter. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains the specified delimiter. The call will block + * until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains the + * delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param delim The delimiter string. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the delimiter. + * + * @throws asio::system_error Thrown on failure. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond the delimiter. An application will typically leave + * that data in the streambuf for a subsequent read_until operation to examine. + * + * @par Example + * To read data into a streambuf until a newline is encountered: + * @code asio::streambuf b; + * asio::read_until(s, b, "\r\n"); + * std::istream is(&b); + * std::string line; + * std::getline(is, line); @endcode + */ +template +std::size_t read_until(SyncReadStream& s, + asio::basic_streambuf& b, const std::string& delim); + +/// Read data into a streambuf until it contains a specified delimiter. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains the specified delimiter. The call will block + * until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains the + * delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param delim The delimiter string. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the delimiter. Returns 0 if an error occurred. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond the delimiter. An application will typically leave + * that data in the streambuf for a subsequent read_until operation to examine. + */ +template +std::size_t read_until(SyncReadStream& s, + asio::basic_streambuf& b, const std::string& delim, + asio::error_code& ec); + +/// Read data into a streambuf until some part of the data it contains matches +/// a regular expression. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains some data that matches a regular expression. + * The call will block until one of the following conditions is true: + * + * @li A substring of the streambuf's get area matches the regular expression. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains data that + * matches the regular expression, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param expr The regular expression. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the substring that matches the regular expression. + * + * @throws asio::system_error Thrown on failure. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond that which matched the regular expression. An + * application will typically leave that data in the streambuf for a subsequent + * read_until operation to examine. + * + * @par Example + * To read data into a streambuf until a CR-LF sequence is encountered: + * @code asio::streambuf b; + * asio::read_until(s, b, boost::regex("\r\n")); + * std::istream is(&b); + * std::string line; + * std::getline(is, line); @endcode + */ +template +std::size_t read_until(SyncReadStream& s, + asio::basic_streambuf& b, const boost::regex& expr); + +/// Read data into a streambuf until some part of the data it contains matches +/// a regular expression. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains some data that matches a regular expression. + * The call will block until one of the following conditions is true: + * + * @li A substring of the streambuf's get area matches the regular expression. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains data that + * matches the regular expression, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param expr The regular expression. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the substring that matches the regular expression. Returns 0 if an error + * occurred. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond that which matched the regular expression. An + * application will typically leave that data in the streambuf for a subsequent + * read_until operation to examine. + */ +template +std::size_t read_until(SyncReadStream& s, + asio::basic_streambuf& b, const boost::regex& expr, + asio::error_code& ec); + +/// Read data into a streambuf until a function object indicates a match. +/** + * This function is used to read data into the specified streambuf until a + * user-defined match condition function object, when applied to the data + * contained in the streambuf, indicates a successful match. The call will + * block until one of the following conditions is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the match condition function object already indicates + * a match, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @returns The number of bytes in the streambuf's get area that have been fully + * consumed by the match function. + * + * @throws asio::system_error Thrown on failure. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond that which matched the function object. An application + * will typically leave that data in the streambuf for a subsequent + * + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + * + * @par Examples + * To read data into a streambuf until whitespace is encountered: + * @code typedef asio::buffers_iterator< + * asio::streambuf::const_buffers_type> iterator; + * + * std::pair + * match_whitespace(iterator begin, iterator end) + * { + * iterator i = begin; + * while (i != end) + * if (std::isspace(*i++)) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * ... + * asio::streambuf b; + * asio::read_until(s, b, match_whitespace); + * @endcode + * + * To read data into a streambuf until a matching character is found: + * @code class match_char + * { + * public: + * explicit match_char(char c) : c_(c) {} + * + * template + * std::pair operator()( + * Iterator begin, Iterator end) const + * { + * Iterator i = begin; + * while (i != end) + * if (c_ == *i++) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * + * private: + * char c_; + * }; + * + * namespace asio { + * template <> struct is_match_condition + * : public boost::true_type {}; + * } // namespace asio + * ... + * asio::streambuf b; + * asio::read_until(s, b, match_char('a')); + * @endcode + */ +template +std::size_t read_until(SyncReadStream& s, + asio::basic_streambuf& b, MatchCondition match_condition, + typename boost::enable_if >::type* = 0); + +/// Read data into a streambuf until a function object indicates a match. +/** + * This function is used to read data into the specified streambuf until a + * user-defined match condition function object, when applied to the data + * contained in the streambuf, indicates a successful match. The call will + * block until one of the following conditions is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the match condition function object already indicates + * a match, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the streambuf's get area that have been fully + * consumed by the match function. Returns 0 if an error occurred. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond that which matched the function object. An application + * will typically leave that data in the streambuf for a subsequent + * + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + */ +template +std::size_t read_until(SyncReadStream& s, + asio::basic_streambuf& b, + MatchCondition match_condition, asio::error_code& ec, + typename boost::enable_if >::type* = 0); + +/*@}*/ +/** + * @defgroup async_read_until asio::async_read_until + * + * @brief Start an asynchronous operation to read data into a streambuf until it + * contains a delimiter, matches a regular expression, or a function object + * indicates a match. + */ +/*@{*/ + +/// Start an asynchronous operation to read data into a streambuf until it +/// contains a specified delimiter. +/** + * This function is used to asynchronously read data into the specified + * streambuf until the streambuf's get area contains the specified delimiter. + * The function call always returns immediately. The asynchronous operation + * will continue until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function. If the streambuf's get area already contains the + * delimiter, the asynchronous operation completes immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. Ownership of + * the streambuf is retained by the caller, which must guarantee that it remains + * valid until the handler is called. + * + * @param delim The delimiter character. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // The number of bytes in the streambuf's get + * // area up to and including the delimiter. + * // 0 if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note After a successful async_read_until operation, the streambuf may + * contain additional data beyond the delimiter. An application will typically + * leave that data in the streambuf for a subsequent async_read_until operation + * to examine. + * + * @par Example + * To asynchronously read data into a streambuf until a newline is encountered: + * @code asio::streambuf b; + * ... + * void handler(const asio::error_code& e, std::size_t size) + * { + * if (!e) + * { + * std::istream is(&b); + * std::string line; + * std::getline(is, line); + * ... + * } + * } + * ... + * asio::async_read_until(s, b, '\n', handler); @endcode + */ +template +void async_read_until(AsyncReadStream& s, + asio::basic_streambuf& b, + char delim, ReadHandler handler); + +/// Start an asynchronous operation to read data into a streambuf until it +/// contains a specified delimiter. +/** + * This function is used to asynchronously read data into the specified + * streambuf until the streambuf's get area contains the specified delimiter. + * The function call always returns immediately. The asynchronous operation + * will continue until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function. If the streambuf's get area already contains the + * delimiter, the asynchronous operation completes immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. Ownership of + * the streambuf is retained by the caller, which must guarantee that it remains + * valid until the handler is called. + * + * @param delim The delimiter string. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // The number of bytes in the streambuf's get + * // area up to and including the delimiter. + * // 0 if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note After a successful async_read_until operation, the streambuf may + * contain additional data beyond the delimiter. An application will typically + * leave that data in the streambuf for a subsequent async_read_until operation + * to examine. + * + * @par Example + * To asynchronously read data into a streambuf until a newline is encountered: + * @code asio::streambuf b; + * ... + * void handler(const asio::error_code& e, std::size_t size) + * { + * if (!e) + * { + * std::istream is(&b); + * std::string line; + * std::getline(is, line); + * ... + * } + * } + * ... + * asio::async_read_until(s, b, "\r\n", handler); @endcode + */ +template +void async_read_until(AsyncReadStream& s, + asio::basic_streambuf& b, const std::string& delim, + ReadHandler handler); + +/// Start an asynchronous operation to read data into a streambuf until some +/// part of its data matches a regular expression. +/** + * This function is used to asynchronously read data into the specified + * streambuf until the streambuf's get area contains some data that matches a + * regular expression. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li A substring of the streambuf's get area matches the regular expression. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function. If the streambuf's get area already contains data + * that matches the regular expression, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. Ownership of + * the streambuf is retained by the caller, which must guarantee that it remains + * valid until the handler is called. + * + * @param expr The regular expression. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // The number of bytes in the streambuf's get + * // area up to and including the substring + * // that matches the regular. expression. + * // 0 if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note After a successful async_read_until operation, the streambuf may + * contain additional data beyond that which matched the regular expression. An + * application will typically leave that data in the streambuf for a subsequent + * async_read_until operation to examine. + * + * @par Example + * To asynchronously read data into a streambuf until a CR-LF sequence is + * encountered: + * @code asio::streambuf b; + * ... + * void handler(const asio::error_code& e, std::size_t size) + * { + * if (!e) + * { + * std::istream is(&b); + * std::string line; + * std::getline(is, line); + * ... + * } + * } + * ... + * asio::async_read_until(s, b, boost::regex("\r\n"), handler); @endcode + */ +template +void async_read_until(AsyncReadStream& s, + asio::basic_streambuf& b, const boost::regex& expr, + ReadHandler handler); + +/// Start an asynchronous operation to read data into a streambuf until a +/// function object indicates a match. +/** + * This function is used to asynchronously read data into the specified + * streambuf until a user-defined match condition function object, when applied + * to the data contained in the streambuf, indicates a successful match. The + * function call always returns immediately. The asynchronous operation will + * continue until one of the following conditions is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function. If the match condition function object already + * indicates a match, the operation completes immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // The number of bytes in the streambuf's get + * // area that have been fully consumed by the + * // match function. O if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note After a successful async_read_until operation, the streambuf may + * contain additional data beyond that which matched the function object. An + * application will typically leave that data in the streambuf for a subsequent + * async_read_until operation to examine. + * + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + * + * @par Examples + * To asynchronously read data into a streambuf until whitespace is encountered: + * @code typedef asio::buffers_iterator< + * asio::streambuf::const_buffers_type> iterator; + * + * std::pair + * match_whitespace(iterator begin, iterator end) + * { + * iterator i = begin; + * while (i != end) + * if (std::isspace(*i++)) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * ... + * void handler(const asio::error_code& e, std::size_t size); + * ... + * asio::streambuf b; + * asio::async_read_until(s, b, match_whitespace, handler); + * @endcode + * + * To asynchronously read data into a streambuf until a matching character is + * found: + * @code class match_char + * { + * public: + * explicit match_char(char c) : c_(c) {} + * + * template + * std::pair operator()( + * Iterator begin, Iterator end) const + * { + * Iterator i = begin; + * while (i != end) + * if (c_ == *i++) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * + * private: + * char c_; + * }; + * + * namespace asio { + * template <> struct is_match_condition + * : public boost::true_type {}; + * } // namespace asio + * ... + * void handler(const asio::error_code& e, std::size_t size); + * ... + * asio::streambuf b; + * asio::async_read_until(s, b, match_char('a'), handler); + * @endcode + */ +template +void async_read_until(AsyncReadStream& s, + asio::basic_streambuf& b, + MatchCondition match_condition, ReadHandler handler, + typename boost::enable_if >::type* = 0); + +/*@}*/ + +} // namespace asio + +#include "asio/impl/read_until.ipp" + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_READ_UNTIL_HPP diff --git a/libtorrent/include/asio/serial_port.hpp b/libtorrent/include/asio/serial_port.hpp new file mode 100644 index 000000000..608ba299a --- /dev/null +++ b/libtorrent/include/asio/serial_port.hpp @@ -0,0 +1,38 @@ +// +// serial_port.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_SERIAL_PORT_HPP +#define ASIO_SERIAL_PORT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/basic_serial_port.hpp" + +#if defined(ASIO_HAS_SERIAL_PORT) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { + +/// Typedef for the typical usage of a serial port. +typedef basic_serial_port<> serial_port; + +} // namespace asio + +#endif // defined(ASIO_HAS_SERIAL_PORT) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_SERIAL_PORT_HPP diff --git a/libtorrent/include/asio/serial_port_base.hpp b/libtorrent/include/asio/serial_port_base.hpp new file mode 100644 index 000000000..2f3d7025b --- /dev/null +++ b/libtorrent/include/asio/serial_port_base.hpp @@ -0,0 +1,157 @@ +// +// serial_port_base.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_SERIAL_PORT_BASE_HPP +#define ASIO_SERIAL_PORT_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# include +#endif +#include "asio/detail/pop_options.hpp" + +#include "asio/error_code.hpp" +#include "asio/detail/socket_types.hpp" + +#if defined(GENERATING_DOCUMENTATION) +# define ASIO_OPTION_STORAGE implementation_defined +#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) +# define ASIO_OPTION_STORAGE DCB +#else +# define ASIO_OPTION_STORAGE termios +#endif + +namespace asio { + +/// The serial_port_base class is used as a base for the basic_serial_port class +/// template so that we have a common place to define the serial port options. +class serial_port_base +{ +public: + /// Serial port option to permit changing the baud rate. + /** + * Implements changing the baud rate for a given serial port. + */ + class baud_rate + { + public: + explicit baud_rate(unsigned int rate = 0); + unsigned int value() const; + asio::error_code store(ASIO_OPTION_STORAGE& storage, + asio::error_code& ec) const; + asio::error_code load(const ASIO_OPTION_STORAGE& storage, + asio::error_code& ec); + private: + unsigned int value_; + }; + + /// Serial port option to permit changing the flow control. + /** + * Implements changing the flow control for a given serial port. + */ + class flow_control + { + public: + enum type { none, software, hardware }; + explicit flow_control(type t = none); + type value() const; + asio::error_code store(ASIO_OPTION_STORAGE& storage, + asio::error_code& ec) const; + asio::error_code load(const ASIO_OPTION_STORAGE& storage, + asio::error_code& ec); + private: + type value_; + }; + + /// Serial port option to permit changing the parity. + /** + * Implements changing the parity for a given serial port. + */ + class parity + { + public: + enum type { none, odd, even }; + explicit parity(type t = none); + type value() const; + asio::error_code store(ASIO_OPTION_STORAGE& storage, + asio::error_code& ec) const; + asio::error_code load(const ASIO_OPTION_STORAGE& storage, + asio::error_code& ec); + private: + type value_; + }; + + /// Serial port option to permit changing the number of stop bits. + /** + * Implements changing the number of stop bits for a given serial port. + */ + class stop_bits + { + public: + enum type { one, onepointfive, two }; + explicit stop_bits(type t = one); + type value() const; + asio::error_code store(ASIO_OPTION_STORAGE& storage, + asio::error_code& ec) const; + asio::error_code load(const ASIO_OPTION_STORAGE& storage, + asio::error_code& ec); + private: + type value_; + }; + + /// Serial port option to permit changing the character size. + /** + * Implements changing the character size for a given serial port. + */ + class character_size + { + public: + explicit character_size(unsigned int t = 8); + unsigned int value() const; + asio::error_code store(ASIO_OPTION_STORAGE& storage, + asio::error_code& ec) const; + asio::error_code load(const ASIO_OPTION_STORAGE& storage, + asio::error_code& ec); + private: + unsigned int value_; + }; + +protected: + /// Protected destructor to prevent deletion through this type. + ~serial_port_base() + { + } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +private: + // Workaround to enable the empty base optimisation with Borland C++. + char dummy_; +#endif +}; + +} // namespace asio + +#include "asio/impl/serial_port_base.ipp" + +#undef ASIO_OPTION_STORAGE + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_SERIAL_PORT_BASE_HPP diff --git a/libtorrent/include/asio/serial_port_service.hpp b/libtorrent/include/asio/serial_port_service.hpp new file mode 100644 index 000000000..e77a53ee4 --- /dev/null +++ b/libtorrent/include/asio/serial_port_service.hpp @@ -0,0 +1,222 @@ +// +// serial_port_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_SERIAL_PORT_SERVICE_HPP +#define ASIO_SERIAL_PORT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/service_base.hpp" +#include "asio/detail/reactive_serial_port_service.hpp" +#include "asio/detail/win_iocp_serial_port_service.hpp" + +#if !defined(ASIO_DISABLE_SERIAL_PORT) +# if defined(ASIO_HAS_IOCP) \ + || !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# define ASIO_HAS_SERIAL_PORT 1 +# endif // defined(ASIO_HAS_IOCP) +#endif // !defined(ASIO_DISABLE_STREAM_HANDLE) + +#if defined(ASIO_HAS_SERIAL_PORT) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { + +/// Default service implementation for a serial port. +class serial_port_service +#if defined(GENERATING_DOCUMENTATION) + : public asio::io_service::service +#else + : public asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. +#if defined(ASIO_HAS_IOCP) + typedef detail::win_iocp_serial_port_service service_impl_type; +#elif defined(ASIO_HAS_EPOLL) + typedef detail::reactive_serial_port_service< + detail::epoll_reactor > service_impl_type; +#elif defined(ASIO_HAS_KQUEUE) + typedef detail::reactive_serial_port_service< + detail::kqueue_reactor > service_impl_type; +#elif defined(ASIO_HAS_DEV_POLL) + typedef detail::reactive_serial_port_service< + detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_serial_port_service< + detail::select_reactor > service_impl_type; +#endif + +public: + /// The type of a serial port implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native handle type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new serial port service for the specified io_service. + explicit serial_port_service(asio::io_service& io_service) + : asio::detail::service_base(io_service), + service_impl_(asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new serial port implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a serial port implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Open a serial port. + asio::error_code open(implementation_type& impl, + const std::string& device, asio::error_code& ec) + { + return service_impl_.open(impl, device, ec); + } + + /// Assign an existing native handle to a serial port. + asio::error_code assign(implementation_type& impl, + const native_type& native_handle, asio::error_code& ec) + { + return service_impl_.assign(impl, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a serial port implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native handle implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the handle. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Set a serial port option. + template + asio::error_code set_option(implementation_type& impl, + const SettableSerialPortOption& option, asio::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a serial port option. + template + asio::error_code get_option(const implementation_type& impl, + GettableSerialPortOption& option, asio::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Send a break sequence to the serial port. + asio::error_code send_break(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.send_break(impl, ec); + } + + /// Write the given data to the stream. + template + std::size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return service_impl_.write_some(impl, buffers, ec); + } + + /// Start an asynchronous write. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, WriteHandler handler) + { + service_impl_.async_write_some(impl, buffers, handler); + } + + /// Read some data from the stream. + template + std::size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return service_impl_.read_some(impl, buffers, ec); + } + + /// Start an asynchronous read. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, ReadHandler handler) + { + service_impl_.async_read_some(impl, buffers, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace asio + +#endif // defined(ASIO_HAS_SERIAL_PORT) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_SERIAL_PORT_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/socket_acceptor_service.hpp b/libtorrent/include/asio/socket_acceptor_service.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/socket_acceptor_service.hpp rename to libtorrent/include/asio/socket_acceptor_service.hpp diff --git a/libtorrent/include/libtorrent/asio/socket_base.hpp b/libtorrent/include/asio/socket_base.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/socket_base.hpp rename to libtorrent/include/asio/socket_base.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl.hpp b/libtorrent/include/asio/ssl.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl.hpp rename to libtorrent/include/asio/ssl.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl/basic_context.hpp b/libtorrent/include/asio/ssl/basic_context.hpp old mode 100755 new mode 100644 similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl/basic_context.hpp rename to libtorrent/include/asio/ssl/basic_context.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl/context.hpp b/libtorrent/include/asio/ssl/context.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl/context.hpp rename to libtorrent/include/asio/ssl/context.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl/context_base.hpp b/libtorrent/include/asio/ssl/context_base.hpp old mode 100755 new mode 100644 similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl/context_base.hpp rename to libtorrent/include/asio/ssl/context_base.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl/context_service.hpp b/libtorrent/include/asio/ssl/context_service.hpp old mode 100755 new mode 100644 similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl/context_service.hpp rename to libtorrent/include/asio/ssl/context_service.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_context_service.hpp b/libtorrent/include/asio/ssl/detail/openssl_context_service.hpp old mode 100755 new mode 100644 similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl/detail/openssl_context_service.hpp rename to libtorrent/include/asio/ssl/detail/openssl_context_service.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_init.hpp b/libtorrent/include/asio/ssl/detail/openssl_init.hpp old mode 100755 new mode 100644 similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl/detail/openssl_init.hpp rename to libtorrent/include/asio/ssl/detail/openssl_init.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_operation.hpp b/libtorrent/include/asio/ssl/detail/openssl_operation.hpp old mode 100755 new mode 100644 similarity index 98% rename from libtorrent/include/libtorrent/asio/ssl/detail/openssl_operation.hpp rename to libtorrent/include/asio/ssl/detail/openssl_operation.hpp index 503559e7f..c8603ac1e --- a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_operation.hpp +++ b/libtorrent/include/asio/ssl/detail/openssl_operation.hpp @@ -168,14 +168,11 @@ public: ((::SSL_get_shutdown( session_ ) & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN); - if (is_shut_down_sent && is_shut_down_received && is_operation_done) + if (is_shut_down_sent && is_shut_down_received && is_operation_done && !is_write_needed) // SSL connection is shut down cleanly return handler_(asio::error_code(), 1); - if (is_shut_down_received && !is_write_needed) - return handler_(asio::error::eof, 0); - - if (is_shut_down_received) + if (is_shut_down_received && !is_operation_done) // Shutdown has been requested, while we were reading or writing... // abort our action... return handler_(asio::error::shut_down, 0); @@ -225,7 +222,7 @@ public: return start(); } - else if (is_read_needed) + else if (is_read_needed || (is_shut_down_sent && !is_shut_down_received)) { return read_(); } diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_stream_service.hpp b/libtorrent/include/asio/ssl/detail/openssl_stream_service.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl/detail/openssl_stream_service.hpp rename to libtorrent/include/asio/ssl/detail/openssl_stream_service.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_types.hpp b/libtorrent/include/asio/ssl/detail/openssl_types.hpp old mode 100755 new mode 100644 similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl/detail/openssl_types.hpp rename to libtorrent/include/asio/ssl/detail/openssl_types.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl/stream.hpp b/libtorrent/include/asio/ssl/stream.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl/stream.hpp rename to libtorrent/include/asio/ssl/stream.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl/stream_base.hpp b/libtorrent/include/asio/ssl/stream_base.hpp old mode 100755 new mode 100644 similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl/stream_base.hpp rename to libtorrent/include/asio/ssl/stream_base.hpp diff --git a/libtorrent/include/libtorrent/asio/ssl/stream_service.hpp b/libtorrent/include/asio/ssl/stream_service.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/ssl/stream_service.hpp rename to libtorrent/include/asio/ssl/stream_service.hpp diff --git a/libtorrent/include/libtorrent/asio/strand.hpp b/libtorrent/include/asio/strand.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/strand.hpp rename to libtorrent/include/asio/strand.hpp diff --git a/libtorrent/include/libtorrent/asio/stream_socket_service.hpp b/libtorrent/include/asio/stream_socket_service.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/stream_socket_service.hpp rename to libtorrent/include/asio/stream_socket_service.hpp diff --git a/libtorrent/include/libtorrent/asio/streambuf.hpp b/libtorrent/include/asio/streambuf.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/streambuf.hpp rename to libtorrent/include/asio/streambuf.hpp diff --git a/libtorrent/include/libtorrent/asio/system_error.hpp b/libtorrent/include/asio/system_error.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/system_error.hpp rename to libtorrent/include/asio/system_error.hpp diff --git a/libtorrent/include/libtorrent/asio/thread.hpp b/libtorrent/include/asio/thread.hpp similarity index 97% rename from libtorrent/include/libtorrent/asio/thread.hpp rename to libtorrent/include/asio/thread.hpp index 7cc8cdf0b..b0f786c6b 100644 --- a/libtorrent/include/libtorrent/asio/thread.hpp +++ b/libtorrent/include/asio/thread.hpp @@ -58,7 +58,7 @@ public: */ template explicit thread(Function f) - : impl_(f) + : impl_(f, asio::detail::thread::external) { } diff --git a/libtorrent/include/libtorrent/asio/time_traits.hpp b/libtorrent/include/asio/time_traits.hpp similarity index 100% rename from libtorrent/include/libtorrent/asio/time_traits.hpp rename to libtorrent/include/asio/time_traits.hpp diff --git a/libtorrent/include/libtorrent/asio/version.hpp b/libtorrent/include/asio/version.hpp similarity index 94% rename from libtorrent/include/libtorrent/asio/version.hpp rename to libtorrent/include/asio/version.hpp index 5da4fd99c..df2fa9f84 100644 --- a/libtorrent/include/libtorrent/asio/version.hpp +++ b/libtorrent/include/asio/version.hpp @@ -18,6 +18,6 @@ // ASIO_VERSION % 100 is the sub-minor version // ASIO_VERSION / 100 % 1000 is the minor version // ASIO_VERSION / 100000 is the major version -#define ASIO_VERSION 100000 // 1.0.0 +#define ASIO_VERSION 100100 // 1.1.0 #endif // ASIO_VERSION_HPP diff --git a/libtorrent/include/asio/windows/basic_handle.hpp b/libtorrent/include/asio/windows/basic_handle.hpp new file mode 100644 index 000000000..f436436b7 --- /dev/null +++ b/libtorrent/include/asio/windows/basic_handle.hpp @@ -0,0 +1,211 @@ +// +// basic_handle.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_WINDOWS_BASIC_HANDLE_HPP +#define ASIO_WINDOWS_BASIC_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/basic_io_object.hpp" +#include "asio/error.hpp" +#include "asio/detail/throw_error.hpp" + +namespace asio { +namespace windows { + +/// Provides Windows handle functionality. +/** + * The windows::basic_handle class template provides the ability to wrap a + * Windows handle. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_handle + : public basic_io_object +{ +public: + /// The native representation of a handle. + typedef typename HandleService::native_type native_type; + + /// A basic_handle is always the lowest layer. + typedef basic_handle lowest_layer_type; + + /// Construct a basic_handle without opening it. + /** + * This constructor creates a handle without opening it. + * + * @param io_service The io_service object that the handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + */ + explicit basic_handle(asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Construct a basic_handle on an existing native handle. + /** + * This constructor creates a handle object to hold an existing native handle. + * + * @param io_service The io_service object that the handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + * + * @param native_handle A native handle. + * + * @throws asio::system_error Thrown on failure. + */ + basic_handle(asio::io_service& io_service, + const native_type& native_handle) + : basic_io_object(io_service) + { + asio::error_code ec; + this->service.assign(this->implementation, native_handle, ec); + asio::detail::throw_error(ec); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_handle cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Assign an existing native handle to the handle. + /* + * This function opens the handle to hold an existing native handle. + * + * @param native_handle A native handle. + * + * @throws asio::system_error Thrown on failure. + */ + void assign(const native_type& native_handle) + { + asio::error_code ec; + this->service.assign(this->implementation, native_handle, ec); + asio::detail::throw_error(ec); + } + + /// Assign an existing native handle to the handle. + /* + * This function opens the handle to hold an existing native handle. + * + * @param native_handle A native handle. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code assign(const native_type& native_handle, + asio::error_code& ec) + { + return this->service.assign(this->implementation, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open() const + { + return this->service.is_open(this->implementation); + } + + /// Close the handle. + /** + * This function is used to close the handle. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + */ + void close() + { + asio::error_code ec; + this->service.close(this->implementation, ec); + asio::detail::throw_error(ec); + } + + /// Close the handle. + /** + * This function is used to close the handle. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code close(asio::error_code& ec) + { + return this->service.close(this->implementation, ec); + } + + /// Get the native handle representation. + /** + * This function may be used to obtain the underlying representation of the + * handle. This is intended to allow access to native handle functionality + * that is not otherwise provided. + */ + native_type native() + { + return this->service.native(this->implementation); + } + + /// Cancel all asynchronous operations associated with the handle. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + */ + void cancel() + { + asio::error_code ec; + this->service.cancel(this->implementation, ec); + asio::detail::throw_error(ec); + } + + /// Cancel all asynchronous operations associated with the handle. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + asio::error_code cancel(asio::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + +protected: + /// Protected destructor to prevent deletion through this type. + ~basic_handle() + { + } +}; + +} // namespace windows +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_WINDOWS_BASIC_HANDLE_HPP diff --git a/libtorrent/include/asio/windows/basic_random_access_handle.hpp b/libtorrent/include/asio/windows/basic_random_access_handle.hpp new file mode 100644 index 000000000..3f015619e --- /dev/null +++ b/libtorrent/include/asio/windows/basic_random_access_handle.hpp @@ -0,0 +1,320 @@ +// +// basic_random_access_handle.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP +#define ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/error.hpp" +#include "asio/windows/basic_handle.hpp" +#include "asio/windows/random_access_handle_service.hpp" +#include "asio/detail/throw_error.hpp" + +#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace windows { + +/// Provides random-access handle functionality. +/** + * The windows::basic_random_access_handle class template provides asynchronous + * and blocking random-access handle functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_random_access_handle + : public basic_handle +{ +public: + /// The native representation of a handle. + typedef typename RandomAccessHandleService::native_type native_type; + + /// Construct a basic_random_access_handle without opening it. + /** + * This constructor creates a random-access handle without opening it. The + * handle needs to be opened before data can be written to or or read from it. + * + * @param io_service The io_service object that the random-access handle will + * use to dispatch handlers for any asynchronous operations performed on the + * handle. + */ + explicit basic_random_access_handle(asio::io_service& io_service) + : basic_handle(io_service) + { + } + + /// Construct a basic_random_access_handle on an existing native handle. + /** + * This constructor creates a random-access handle object to hold an existing + * native handle. + * + * @param io_service The io_service object that the random-access handle will + * use to dispatch handlers for any asynchronous operations performed on the + * handle. + * + * @param native_handle The new underlying handle implementation. + * + * @throws asio::system_error Thrown on failure. + */ + basic_random_access_handle(asio::io_service& io_service, + const native_type& native_handle) + : basic_handle(io_service, native_handle) + { + } + + /// Write some data to the handle at the specified offset. + /** + * This function is used to write data to the random-access handle. The + * function call will block until one or more bytes of the data has been + * written successfully, or until an error occurs. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @returns The number of bytes written. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some_at operation may not write all of the data. Consider + * using the @ref write_at function if you need to ensure that all data is + * written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.write_some_at(42, asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some_at(boost::uint64_t offset, + const ConstBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->service.write_some_at( + this->implementation, offset, buffers, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the handle at the specified offset. + /** + * This function is used to write data to the random-access handle. The + * function call will block until one or more bytes of the data has been + * written successfully, or until an error occurs. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write_at function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some_at(boost::uint64_t offset, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return this->service.write_some_at( + this->implementation, offset, buffers, ec); + } + + /// Start an asynchronous write at the specified offset. + /** + * This function is used to asynchronously write data to the random-access + * handle. The function call always returns immediately. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write_at function if you need to ensure that + * all data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_write_some_at(42, asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some_at(boost::uint64_t offset, + const ConstBufferSequence& buffers, WriteHandler handler) + { + this->service.async_write_some_at( + this->implementation, offset, buffers, handler); + } + + /// Read some data from the handle at the specified offset. + /** + * This function is used to read data from the random-access handle. The + * function call will block until one or more bytes of data has been read + * successfully, or until an error occurs. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read_at function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.read_some_at(42, asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some_at(boost::uint64_t offset, + const MutableBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->service.read_some_at( + this->implementation, offset, buffers, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the handle at the specified offset. + /** + * This function is used to read data from the random-access handle. The + * function call will block until one or more bytes of data has been read + * successfully, or until an error occurs. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read_at function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some_at(boost::uint64_t offset, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return this->service.read_some_at( + this->implementation, offset, buffers, ec); + } + + /// Start an asynchronous read at the specified offset. + /** + * This function is used to asynchronously read data from the random-access + * handle. The function call always returns immediately. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read_at function if you need to ensure that + * the requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_read_some_at(42, asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some_at(boost::uint64_t offset, + const MutableBufferSequence& buffers, ReadHandler handler) + { + this->service.async_read_some_at( + this->implementation, offset, buffers, handler); + } +}; + +} // namespace windows +} // namespace asio + +#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP diff --git a/libtorrent/include/asio/windows/basic_stream_handle.hpp b/libtorrent/include/asio/windows/basic_stream_handle.hpp new file mode 100644 index 000000000..aca40aff1 --- /dev/null +++ b/libtorrent/include/asio/windows/basic_stream_handle.hpp @@ -0,0 +1,302 @@ +// +// basic_stream_handle.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP +#define ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/error.hpp" +#include "asio/windows/basic_handle.hpp" +#include "asio/windows/stream_handle_service.hpp" +#include "asio/detail/throw_error.hpp" + +#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace windows { + +/// Provides stream-oriented handle functionality. +/** + * The windows::basic_stream_handle class template provides asynchronous and + * blocking stream-oriented handle functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template +class basic_stream_handle + : public basic_handle +{ +public: + /// The native representation of a handle. + typedef typename StreamHandleService::native_type native_type; + + /// Construct a basic_stream_handle without opening it. + /** + * This constructor creates a stream handle without opening it. The handle + * needs to be opened and then connected or accepted before data can be sent + * or received on it. + * + * @param io_service The io_service object that the stream handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + */ + explicit basic_stream_handle(asio::io_service& io_service) + : basic_handle(io_service) + { + } + + /// Construct a basic_stream_handle on an existing native handle. + /** + * This constructor creates a stream handle object to hold an existing native + * handle. + * + * @param io_service The io_service object that the stream handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + * + * @param native_handle The new underlying handle implementation. + * + * @throws asio::system_error Thrown on failure. + */ + basic_stream_handle(asio::io_service& io_service, + const native_type& native_handle) + : basic_handle(io_service, native_handle) + { + } + + /// Write some data to the handle. + /** + * This function is used to write data to the stream handle. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @returns The number of bytes written. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.write_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->service.write_some(this->implementation, buffers, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the handle. + /** + * This function is used to write data to the stream handle. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + asio::error_code& ec) + { + return this->service.write_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the stream handle. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the handle. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_write_some(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + this->service.async_write_some(this->implementation, buffers, handler); + } + + /// Read some data from the handle. + /** + * This function is used to read data from the stream handle. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.read_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->service.read_some(this->implementation, buffers, ec); + asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the handle. + /** + * This function is used to read data from the stream handle. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + asio::error_code& ec) + { + return this->service.read_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the stream handle. + * The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_read_some(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + this->service.async_read_some(this->implementation, buffers, handler); + } +}; + +} // namespace windows +} // namespace asio + +#endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP diff --git a/libtorrent/include/asio/windows/random_access_handle.hpp b/libtorrent/include/asio/windows/random_access_handle.hpp new file mode 100644 index 000000000..7bc8db85a --- /dev/null +++ b/libtorrent/include/asio/windows/random_access_handle.hpp @@ -0,0 +1,39 @@ +// +// random_access_handle.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP +#define ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/windows/basic_random_access_handle.hpp" + +#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace windows { + +/// Typedef for the typical usage of a random-access handle. +typedef basic_random_access_handle<> random_access_handle; + +} // namespace windows +} // namespace asio + +#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP diff --git a/libtorrent/include/asio/windows/random_access_handle_service.hpp b/libtorrent/include/asio/windows/random_access_handle_service.hpp new file mode 100644 index 000000000..3430deb32 --- /dev/null +++ b/libtorrent/include/asio/windows/random_access_handle_service.hpp @@ -0,0 +1,179 @@ +// +// random_access_handle_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP +#define ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/service_base.hpp" +#include "asio/detail/win_iocp_handle_service.hpp" + +#if !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) +# if defined(ASIO_HAS_IOCP) +# define ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1 +# endif // defined(ASIO_HAS_IOCP) +#endif // !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) + +#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace windows { + +/// Default service implementation for a random-access handle. +class random_access_handle_service +#if defined(GENERATING_DOCUMENTATION) + : public asio::io_service::service +#else + : public asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. + typedef detail::win_iocp_handle_service service_impl_type; + +public: + /// The type of a random-access handle implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native handle type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new random-access handle service for the specified io_service. + explicit random_access_handle_service(asio::io_service& io_service) + : asio::detail::service_base< + random_access_handle_service>(io_service), + service_impl_(asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new random-access handle implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a random-access handle implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Assign an existing native handle to a random-access handle. + asio::error_code assign(implementation_type& impl, + const native_type& native_handle, asio::error_code& ec) + { + return service_impl_.assign(impl, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a random-access handle implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native handle implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the handle. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Write the given data at the specified offset. + template + std::size_t write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return service_impl_.write_some_at(impl, offset, buffers, ec); + } + + /// Start an asynchronous write at the specified offset. + template + void async_write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, WriteHandler handler) + { + service_impl_.async_write_some_at(impl, offset, buffers, handler); + } + + /// Read some data from the specified offset. + template + std::size_t read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return service_impl_.read_some_at(impl, offset, buffers, ec); + } + + /// Start an asynchronous read at the specified offset. + template + void async_read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, ReadHandler handler) + { + service_impl_.async_read_some_at(impl, offset, buffers, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace windows +} // namespace asio + +#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP diff --git a/libtorrent/include/asio/windows/stream_handle.hpp b/libtorrent/include/asio/windows/stream_handle.hpp new file mode 100644 index 000000000..84b216d9f --- /dev/null +++ b/libtorrent/include/asio/windows/stream_handle.hpp @@ -0,0 +1,39 @@ +// +// stream_handle.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_WINDOWS_STREAM_HANDLE_HPP +#define ASIO_WINDOWS_STREAM_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/windows/basic_stream_handle.hpp" + +#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace windows { + +/// Typedef for the typical usage of a stream-oriented handle. +typedef basic_stream_handle<> stream_handle; + +} // namespace windows +} // namespace asio + +#endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_WINDOWS_STREAM_HANDLE_HPP diff --git a/libtorrent/include/asio/windows/stream_handle_service.hpp b/libtorrent/include/asio/windows/stream_handle_service.hpp new file mode 100644 index 000000000..26bd529c4 --- /dev/null +++ b/libtorrent/include/asio/windows/stream_handle_service.hpp @@ -0,0 +1,177 @@ +// +// stream_handle_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP +#define ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/error.hpp" +#include "asio/io_service.hpp" +#include "asio/detail/service_base.hpp" +#include "asio/detail/win_iocp_handle_service.hpp" + +#if !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE) +# if defined(ASIO_HAS_IOCP) +# define ASIO_HAS_WINDOWS_STREAM_HANDLE 1 +# endif // defined(ASIO_HAS_IOCP) +#endif // !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE) + +#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace asio { +namespace windows { + +/// Default service implementation for a stream handle. +class stream_handle_service +#if defined(GENERATING_DOCUMENTATION) + : public asio::io_service::service +#else + : public asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. + typedef detail::win_iocp_handle_service service_impl_type; + +public: + /// The type of a stream handle implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native handle type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new stream handle service for the specified io_service. + explicit stream_handle_service(asio::io_service& io_service) + : asio::detail::service_base(io_service), + service_impl_(asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new stream handle implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a stream handle implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Assign an existing native handle to a stream handle. + asio::error_code assign(implementation_type& impl, + const native_type& native_handle, asio::error_code& ec) + { + return service_impl_.assign(impl, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a stream handle implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native handle implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the handle. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Write the given data to the stream. + template + std::size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return service_impl_.write_some(impl, buffers, ec); + } + + /// Start an asynchronous write. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, WriteHandler handler) + { + service_impl_.async_write_some(impl, buffers, handler); + } + + /// Read some data from the stream. + template + std::size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return service_impl_.read_some(impl, buffers, ec); + } + + /// Start an asynchronous read. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, ReadHandler handler) + { + service_impl_.async_read_some(impl, buffers, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace windows +} // namespace asio + +#endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/write.hpp b/libtorrent/include/asio/write.hpp similarity index 98% rename from libtorrent/include/libtorrent/asio/write.hpp rename to libtorrent/include/asio/write.hpp index 1c72c1cd5..b1965880b 100644 --- a/libtorrent/include/libtorrent/asio/write.hpp +++ b/libtorrent/include/asio/write.hpp @@ -29,6 +29,8 @@ namespace asio { /** * @defgroup write asio::write + * + * @brief Write a certain amount of data to a stream before returning. */ /*@{*/ @@ -166,7 +168,7 @@ template & b, /*@}*/ /** * @defgroup async_write asio::async_write + * + * @brief Start an asynchronous operation to write a certain amount of data to a + * stream. */ /*@{*/ -/// Start an asynchronous operation to write of all of the supplied data to a +/// Start an asynchronous operation to write all of the supplied data to a /// stream. /** * This function is used to asynchronously write a certain number of bytes of @@ -405,7 +410,7 @@ template = 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +#include "asio/detail/push_options.hpp" +#include +#include +#include +#include "asio/detail/pop_options.hpp" + +#include "asio/basic_streambuf.hpp" +#include "asio/error.hpp" + +namespace asio { + +/** + * @defgroup write_at asio::write_at + * + * @brief Write a certain amount of data at a specified offset before returning. + */ +/*@{*/ + +/// Write all of the supplied data at the specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * device. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code asio::write_at(d, 42, asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code asio::write_at( + * d, offset, buffers, + * asio::transfer_all()); @endcode + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code asio::write_at(d, 42, asio::buffer(data, size), + * asio::transfer_at_least(32)); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, asio::error_code& ec); + +/// Write all of the supplied data at the specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b The basic_streambuf object from which data will be written. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + * + * @note This overload is equivalent to calling: + * @code asio::write_at( + * d, 42, b, + * asio::transfer_all()); @endcode + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, basic_streambuf& b); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b The basic_streambuf object from which data will be written. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws asio::system_error Thrown on failure. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, CompletionCondition completion_condition); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b The basic_streambuf object from which data will be written. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, CompletionCondition completion_condition, + asio::error_code& ec); + +/*@}*/ +/** + * @defgroup async_write_at asio::async_write_at + * + * @brief Start an asynchronous operation to write a certain amount of data at + * the specified offset. + */ +/*@{*/ + +/// Start an asynchronous operation to write all of the supplied data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * asio::async_write_at(d, 42, asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, + const ConstBufferSequence& buffers, WriteHandler handler); + +/// Start an asynchronous operation to write a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's async_write_some_at function are + * required. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code asio::async_write_at(d, 42, + * asio::buffer(data, size), + * asio::transfer_at_least(32), + * handler); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, WriteHandler handler); + +/// Start an asynchronous operation to write all of the supplied data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b A basic_streambuf object from which data will be written. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, WriteHandler handler); + +/// Start an asynchronous operation to write a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b A basic_streambuf object from which data will be written. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest async_write_some_at operation. + * const asio::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's async_write_some_at function are + * required. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const asio::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * asio::io_service::post(). + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, CompletionCondition completion_condition, + WriteHandler handler); + +/*@}*/ + +} // namespace asio + +#include "asio/impl/write_at.ipp" + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_WRITE_AT_HPP diff --git a/libtorrent/include/libtorrent/GeoIP.h b/libtorrent/include/libtorrent/GeoIP.h new file mode 100644 index 000000000..d493eccb9 --- /dev/null +++ b/libtorrent/include/libtorrent/GeoIP.h @@ -0,0 +1,180 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* GeoIP.h + * + * Copyright (C) 2006 MaxMind LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef GEOIP_H +#define GEOIP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include /* for fstat */ +#include /* for fstat */ + +#define SEGMENT_RECORD_LENGTH 3 +#define STANDARD_RECORD_LENGTH 3 +#define ORG_RECORD_LENGTH 4 +#define MAX_RECORD_LENGTH 4 +#define NUM_DB_TYPES 20 + +typedef struct GeoIPTag { + FILE *GeoIPDatabase; + char *file_path; + unsigned char *cache; + unsigned char *index_cache; + unsigned int *databaseSegments; + char databaseType; + time_t mtime; + int flags; + off_t size; + char record_length; + int charset; /* 0 iso-8859-1 1 utf8 */ + int record_iter; /* used in GeoIP_next_record */ + int netmask; /* netmask of last lookup - set using depth in _GeoIP_seek_record */ +} GeoIP; + + +typedef enum { + GEOIP_CHARSET_ISO_8859_1 = 0, + GEOIP_CHARSET_UTF8 = 1 +} GeoIPCharset; + +typedef struct GeoIPRegionTag { + char country_code[3]; + char region[3]; +} GeoIPRegion; + +typedef enum { + GEOIP_STANDARD = 0, + GEOIP_MEMORY_CACHE = 1, + GEOIP_CHECK_CACHE = 2, + GEOIP_INDEX_CACHE = 4, + GEOIP_MMAP_CACHE = 8, +} GeoIPOptions; + +typedef enum { + GEOIP_COUNTRY_EDITION = 1, + GEOIP_REGION_EDITION_REV0 = 7, + GEOIP_CITY_EDITION_REV0 = 6, + GEOIP_ORG_EDITION = 5, + GEOIP_ISP_EDITION = 4, + GEOIP_CITY_EDITION_REV1 = 2, + GEOIP_REGION_EDITION_REV1 = 3, + GEOIP_PROXY_EDITION = 8, + GEOIP_ASNUM_EDITION = 9, + GEOIP_NETSPEED_EDITION = 10, + GEOIP_DOMAIN_EDITION = 11 +} GeoIPDBTypes; + +typedef enum { + GEOIP_ANON_PROXY = 1, + GEOIP_HTTP_X_FORWARDED_FOR_PROXY = 2, + GEOIP_HTTP_CLIENT_IP_PROXY = 3, +} GeoIPProxyTypes; + +typedef enum { + GEOIP_UNKNOWN_SPEED = 0, + GEOIP_DIALUP_SPEED = 1, + GEOIP_CABLEDSL_SPEED = 2, + GEOIP_CORPORATE_SPEED = 3, +} GeoIPNetspeedValues; + +extern char **GeoIPDBFileName; +extern const char * GeoIPDBDescription[NUM_DB_TYPES]; +extern const char *GeoIPCountryDBFileName; +extern const char *GeoIPRegionDBFileName; +extern const char *GeoIPCityDBFileName; +extern const char *GeoIPOrgDBFileName; +extern const char *GeoIPISPDBFileName; + +extern const char GeoIP_country_code[253][3]; +extern const char GeoIP_country_code3[253][4]; +extern const char * GeoIP_country_name[253]; +extern const char GeoIP_country_continent[253][3]; + +#ifdef DLL +#define GEOIP_API __declspec(dllexport) +#else +#define GEOIP_API +#endif /* DLL */ + +GEOIP_API void GeoIP_setup_custom_directory(char *dir); +GEOIP_API GeoIP* GeoIP_open_type (int type, int flags); +GEOIP_API GeoIP* GeoIP_new(int flags); +GEOIP_API GeoIP* GeoIP_open(const char * filename, int flags); +GEOIP_API int GeoIP_db_avail(int type); +GEOIP_API void GeoIP_delete(GeoIP* gi); +GEOIP_API const char *GeoIP_country_code_by_addr (GeoIP* gi, const char *addr); +GEOIP_API const char *GeoIP_country_code_by_name (GeoIP* gi, const char *host); +GEOIP_API const char *GeoIP_country_code3_by_addr (GeoIP* gi, const char *addr); +GEOIP_API const char *GeoIP_country_code3_by_name (GeoIP* gi, const char *host); +GEOIP_API const char *GeoIP_country_name_by_addr (GeoIP* gi, const char *addr); +GEOIP_API const char *GeoIP_country_name_by_name (GeoIP* gi, const char *host); +GEOIP_API const char *GeoIP_country_name_by_ipnum (GeoIP* gi, unsigned long ipnum); +GEOIP_API const char *GeoIP_country_code_by_ipnum (GeoIP* gi, unsigned long ipnum); +GEOIP_API const char *GeoIP_country_code3_by_ipnum (GeoIP* gi, unsigned long ipnum); + +/* Deprecated - for backwards compatibility only */ +GEOIP_API int GeoIP_country_id_by_addr (GeoIP* gi, const char *addr); +GEOIP_API int GeoIP_country_id_by_name (GeoIP* gi, const char *host); +GEOIP_API char *GeoIP_org_by_addr (GeoIP* gi, const char *addr); +GEOIP_API char *GeoIP_org_by_name (GeoIP* gi, const char *host); +/* End deprecated */ + +GEOIP_API int GeoIP_id_by_addr (GeoIP* gi, const char *addr); +GEOIP_API int GeoIP_id_by_name (GeoIP* gi, const char *host); +GEOIP_API int GeoIP_id_by_ipnum (GeoIP* gi, unsigned long ipnum); + +GEOIP_API GeoIPRegion * GeoIP_region_by_addr (GeoIP* gi, const char *addr); +GEOIP_API GeoIPRegion * GeoIP_region_by_name (GeoIP* gi, const char *host); +GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum (GeoIP *gi, unsigned long ipnum); + +/* Warning - don't call this after GeoIP_assign_region_by_inetaddr calls */ +GEOIP_API void GeoIPRegion_delete (GeoIPRegion *gir); + +GEOIP_API void GeoIP_assign_region_by_inetaddr(GeoIP* gi, unsigned long inetaddr, GeoIPRegion *gir); + +/* Used to query GeoIP Organization, ISP and AS Number databases */ +GEOIP_API char *GeoIP_name_by_ipnum (GeoIP* gi, unsigned long ipnum); +GEOIP_API char *GeoIP_name_by_addr (GeoIP* gi, const char *addr); +GEOIP_API char *GeoIP_name_by_name (GeoIP* gi, const char *host); + +GEOIP_API char *GeoIP_database_info (GeoIP* gi); +GEOIP_API unsigned char GeoIP_database_edition (GeoIP* gi); + +GEOIP_API int GeoIP_charset (GeoIP* gi); +GEOIP_API int GeoIP_set_charset (GeoIP* gi, int charset); + +GEOIP_API int GeoIP_last_netmask (GeoIP* gi); + +/* Convert region code to region name */ +GEOIP_API const char * GeoIP_region_name_by_code(const char *country_code, const char *region_code); + +/* Get timezone from country and region code */ +GEOIP_API const char * GeoIP_time_zone_by_country_and_region(const char *country_code, const char *region_code); + +#ifdef __cplusplus +} +#endif + +#endif /* GEOIP_H */ diff --git a/libtorrent/include/libtorrent/alert.hpp b/libtorrent/include/libtorrent/alert.hpp old mode 100755 new mode 100644 index ab8065f1f..afa8e978f --- a/libtorrent/include/libtorrent/alert.hpp +++ b/libtorrent/include/libtorrent/alert.hpp @@ -67,23 +67,40 @@ namespace libtorrent { class TORRENT_EXPORT alert { public: + + // only here for backwards compatibility enum severity_t { debug, info, warning, critical, fatal, none }; - alert(severity_t severity, const std::string& msg); + enum category_t + { + error_notification = 0x1, + peer_notification = 0x2, + port_mapping_notification = 0x4, + storage_notification = 0x8, + tracker_notification = 0x10, + debug_notification = 0x20, + status_notification = 0x40, + progress_notification = 0x80, + ip_block_notification = 0x100, + + all_categories = 0xffffffff + }; + + alert(); virtual ~alert(); // a timestamp is automatically created in the constructor ptime timestamp() const; - std::string const& msg() const; + virtual char const* what() const = 0; + virtual std::string message() const = 0; + virtual int category() const = 0; - severity_t severity() const; + severity_t severity() const TORRENT_DEPRECATED { return warning; } virtual std::auto_ptr clone() const = 0; private: - std::string m_msg; - severity_t m_severity; ptime m_timestamp; }; @@ -97,16 +114,18 @@ namespace libtorrent { bool pending() const; std::auto_ptr get(); - void set_severity(alert::severity_t severity); - bool should_post(alert::severity_t severity) const; + template + bool should_post() const { return m_alert_mask & T::static_category; } alert const* wait_for_alert(time_duration max_wait); + void set_alert_mask(int m) { m_alert_mask = m; } + private: std::queue m_alerts; - alert::severity_t m_severity; mutable boost::mutex m_mutex; boost::condition m_condition; + int m_alert_mask; }; struct TORRENT_EXPORT unhandled_alert : std::exception diff --git a/libtorrent/include/libtorrent/alert_types.hpp b/libtorrent/include/libtorrent/alert_types.hpp old mode 100755 new mode 100644 index 02b11e071..a1c556d82 --- a/libtorrent/include/libtorrent/alert_types.hpp +++ b/libtorrent/include/libtorrent/alert_types.hpp @@ -39,59 +39,207 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/peer_connection.hpp" #include "libtorrent/config.hpp" #include "libtorrent/assert.hpp" +#include "libtorrent/identify_client.hpp" + +#include namespace libtorrent { struct TORRENT_EXPORT torrent_alert: alert { - torrent_alert(torrent_handle const& h, alert::severity_t s - , std::string const& msg) - : alert(s, msg) - , handle(h) + torrent_alert(torrent_handle const& h) + : handle(h) {} + virtual std::string message() const + { return handle.is_valid()?handle.name():" - "; } + torrent_handle handle; }; + struct TORRENT_EXPORT peer_alert: torrent_alert + { + peer_alert(torrent_handle const& h, tcp::endpoint const& ip_ + , peer_id const& pid_) + : torrent_alert(h) + , ip(ip_) + , pid(pid_) + {} + + const static int static_category = alert::peer_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + error_code ec; + return torrent_alert::message() + " peer (" + ip.address().to_string(ec) + + ", " + identify_client(pid) + ")"; + } + + tcp::endpoint ip; + peer_id pid; + }; + struct TORRENT_EXPORT tracker_alert: torrent_alert { tracker_alert(torrent_handle const& h - , int times - , int status - , std::string const& url_ - , std::string const& msg) - : torrent_alert(h, alert::warning, msg) - , times_in_row(times) - , status_code(status) + , std::string const& url_) + : torrent_alert(h) , url(url_) - {} + { assert(!url.empty()); } - virtual std::auto_ptr clone() const - { return std::auto_ptr(new tracker_alert(*this)); } + const static int static_category = alert::tracker_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " (" + url + ")"; + } - int times_in_row; - int status_code; std::string url; }; - struct TORRENT_EXPORT tracker_warning_alert: torrent_alert + struct TORRENT_EXPORT file_renamed_alert: torrent_alert { - tracker_warning_alert(torrent_handle const& h - , std::string const& msg) - : torrent_alert(h, alert::warning, msg) + file_renamed_alert(torrent_handle const& h + , std::string const& name_ + , int index_) + : torrent_alert(h) + , name(name_) + , index(index_) {} virtual std::auto_ptr clone() const - { return std::auto_ptr(new tracker_warning_alert(*this)); } + { return std::auto_ptr(new file_renamed_alert(*this)); } + const static int static_category = alert::storage_notification; + virtual int category() const { return static_category; } + virtual char const* what() const { return "file renamed"; } + virtual std::string message() const + { + return torrent_alert::message() + ": file " + + boost::lexical_cast(index) + " renamed to " + + name; + } + + std::string name; + int index; }; - struct TORRENT_EXPORT scrape_reply_alert: torrent_alert + struct TORRENT_EXPORT file_rename_failed_alert: torrent_alert + { + file_rename_failed_alert(torrent_handle const& h + , std::string const& msg_ + , int index_) + : torrent_alert(h) + , msg(msg_) + , index(index_) + {} + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new file_rename_failed_alert(*this)); } + + virtual char const* what() const { return "file rename failed"; } + virtual std::string message() const + { + return torrent_alert::message() + ": failed to rename file " + + boost::lexical_cast(index) + ": " + + msg; + } + + const static int static_category = alert::storage_notification; + virtual int category() const { return static_category; } + + std::string msg; + int index; + }; + + struct TORRENT_EXPORT state_changed_alert: torrent_alert + { + state_changed_alert(torrent_handle const& h + , torrent_status::state_t const& state_) + : torrent_alert(h) + , state(state_) + {} + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new state_changed_alert(*this)); } + + virtual char const* what() const { return "torrent state changed"; } + virtual std::string message() const + { + static char const* state_str[] = + {"checking (q)", "checking", "connecting", "dl metadata" + , "downloading", "finished", "seeding", "allocating"}; + + return torrent_alert::message() + ": state changed to: " + + state_str[state]; + } + + + const static int static_category = alert::status_notification; + virtual int category() const { return static_category; } + + torrent_status::state_t state; + }; + + struct TORRENT_EXPORT tracker_error_alert: tracker_alert + { + tracker_error_alert(torrent_handle const& h + , int times + , int status + , std::string const& url + , std::string const& msg_) + : tracker_alert(h, url) + , times_in_row(times) + , status_code(status) + , msg(msg_) + {} + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new tracker_error_alert(*this)); } + const static int static_category = alert::tracker_notification | alert::error_notification; + virtual int category() const { return static_category; } + virtual char const* what() const { return "tracker error"; } + virtual std::string message() const + { + return tracker_alert::message() + " (" + + boost::lexical_cast(status_code) + + ") " + msg + " (" + boost::lexical_cast(times_in_row) + + ")"; + } + + int times_in_row; + int status_code; + std::string msg; + }; + + struct TORRENT_EXPORT tracker_warning_alert: tracker_alert + { + tracker_warning_alert(torrent_handle const& h + , std::string const& url + , std::string const& msg_) + : tracker_alert(h, url) + , msg(msg_) + {} + + std::string msg; + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new tracker_warning_alert(*this)); } + const static int static_category = alert::tracker_notification | alert::error_notification; + virtual int category() const { return static_category; } + virtual char const* what() const { return "tracker warning"; } + virtual std::string message() const + { + return tracker_alert::message() + " warning: " + msg; + } + }; + + struct TORRENT_EXPORT scrape_reply_alert: tracker_alert { scrape_reply_alert(torrent_handle const& h , int incomplete_ , int complete_ - , std::string const& msg) - : torrent_alert(h, alert::info, msg) + , std::string const& url) + : tracker_alert(h, url) , incomplete(incomplete_) , complete(complete_) {} @@ -101,25 +249,43 @@ namespace libtorrent virtual std::auto_ptr clone() const { return std::auto_ptr(new scrape_reply_alert(*this)); } + virtual char const* what() const { return "tracker scrape reply"; } + virtual std::string message() const + { + return tracker_alert::message() + " scrape reply: " + + boost::lexical_cast(incomplete) + " " + + boost::lexical_cast(complete); + } }; - struct TORRENT_EXPORT scrape_failed_alert: torrent_alert + struct TORRENT_EXPORT scrape_failed_alert: tracker_alert { scrape_failed_alert(torrent_handle const& h - , std::string const& msg) - : torrent_alert(h, alert::warning, msg) + , std::string const& url + , std::string const& msg_) + : tracker_alert(h, url) + , msg(msg_) {} + std::string msg; + virtual std::auto_ptr clone() const { return std::auto_ptr(new scrape_failed_alert(*this)); } + const static int static_category = alert::tracker_notification | alert::error_notification; + virtual int category() const { return static_category; } + virtual char const* what() const { return "tracker scrape failed"; } + virtual std::string message() const + { + return tracker_alert::message() + " scrape failed: " + msg; + } }; - struct TORRENT_EXPORT tracker_reply_alert: torrent_alert + struct TORRENT_EXPORT tracker_reply_alert: tracker_alert { tracker_reply_alert(torrent_handle const& h , int np - , std::string const& msg) - : torrent_alert(h, alert::info, msg) + , std::string const& url) + : tracker_alert(h, url) , num_peers(np) {} @@ -127,103 +293,229 @@ namespace libtorrent virtual std::auto_ptr clone() const { return std::auto_ptr(new tracker_reply_alert(*this)); } + virtual char const* what() const { return "tracker reply"; } + virtual std::string message() const + { + return tracker_alert::message() + " received peers: " + + boost::lexical_cast(num_peers); + } }; - struct TORRENT_EXPORT tracker_announce_alert: torrent_alert + struct TORRENT_EXPORT dht_reply_alert: tracker_alert { - tracker_announce_alert(torrent_handle const& h, std::string const& msg) - : torrent_alert(h, alert::info, msg) + dht_reply_alert(torrent_handle const& h + , int np) + : tracker_alert(h, "") + , num_peers(np) + {} + + int num_peers; + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new dht_reply_alert(*this)); } + virtual char const* what() const { return "DHT reply"; } + virtual std::string message() const + { + return torrent_alert::message() + " received DHT peers: " + + boost::lexical_cast(num_peers); + } + }; + + struct TORRENT_EXPORT tracker_announce_alert: tracker_alert + { + tracker_announce_alert(torrent_handle const& h + , std::string const& url) + : tracker_alert(h, url) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new tracker_announce_alert(*this)); } + virtual char const* what() const { return "tracker announce sent"; } + virtual std::string message() const + { + return tracker_alert::message() + " sending announce"; + } }; struct TORRENT_EXPORT hash_failed_alert: torrent_alert { hash_failed_alert( torrent_handle const& h - , int index - , std::string const& msg) - : torrent_alert(h, alert::info, msg) + , int index) + : torrent_alert(h) , piece_index(index) { TORRENT_ASSERT(index >= 0);} virtual std::auto_ptr clone() const { return std::auto_ptr(new hash_failed_alert(*this)); } + virtual char const* what() const { return "piece hash failed"; } + const static int static_category = alert::status_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " hash for piece " + + boost::lexical_cast(piece_index) + " failed"; + } int piece_index; }; - struct TORRENT_EXPORT peer_ban_alert: torrent_alert + struct TORRENT_EXPORT peer_ban_alert: peer_alert { - peer_ban_alert(tcp::endpoint const& pip, torrent_handle h, std::string const& msg) - : torrent_alert(h, alert::info, msg) - , ip(pip) + peer_ban_alert(torrent_handle h, tcp::endpoint const& ip + , peer_id const& pid) + : peer_alert(h, ip, pid) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new peer_ban_alert(*this)); } - - tcp::endpoint ip; + virtual char const* what() const { return "peer banned"; } + virtual std::string message() const + { + error_code ec; + return peer_alert::message() + " banned peer"; + } }; - struct TORRENT_EXPORT peer_error_alert: alert + struct TORRENT_EXPORT peer_unsnubbed_alert: peer_alert { - peer_error_alert(tcp::endpoint const& pip, peer_id const& pid_, std::string const& msg) - : alert(alert::debug, msg) - , ip(pip) - , pid(pid_) + peer_unsnubbed_alert(torrent_handle h, tcp::endpoint const& ip + , peer_id const& pid) + : peer_alert(h, ip, pid) + {} + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new peer_unsnubbed_alert(*this)); } + virtual char const* what() const { return "peer unsnubbed"; } + virtual std::string message() const + { + return peer_alert::message() + " peer unsnubbed"; + } + }; + + struct TORRENT_EXPORT peer_snubbed_alert: peer_alert + { + peer_snubbed_alert(torrent_handle h, tcp::endpoint const& ip + , peer_id const& pid) + : peer_alert(h, ip, pid) + {} + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new peer_snubbed_alert(*this)); } + virtual char const* what() const { return "peer snubbed"; } + virtual std::string message() const + { + return peer_alert::message() + " peer snubbed"; + } + }; + + struct TORRENT_EXPORT peer_error_alert: peer_alert + { + peer_error_alert(torrent_handle const& h, tcp::endpoint const& ip + , peer_id const& pid, std::string const& msg_) + : peer_alert(h, ip, pid) + , msg(msg_) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new peer_error_alert(*this)); } + virtual char const* what() const { return "peer error"; } + const static int static_category = alert::peer_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + error_code ec; + return peer_alert::message() + " peer error: " + msg; + } - tcp::endpoint ip; - peer_id pid; + std::string msg; }; - struct TORRENT_EXPORT invalid_request_alert: torrent_alert + struct TORRENT_EXPORT peer_connect_alert: peer_alert { - invalid_request_alert( - peer_request const& r - , torrent_handle const& h - , tcp::endpoint const& sender - , peer_id const& pid_ - , std::string const& msg) - : torrent_alert(h, alert::debug, msg) - , ip(sender) + peer_connect_alert(torrent_handle h, tcp::endpoint const& ip + , peer_id const& pid) + : peer_alert(h, ip, pid) + {} + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new peer_connect_alert(*this)); } + virtual char const* what() const { return "connecting to peer"; } + const static int static_category = alert::debug_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return peer_alert::message() + " connecting to peer"; + } + }; + + struct TORRENT_EXPORT peer_disconnected_alert: peer_alert + { + peer_disconnected_alert(torrent_handle const& h, tcp::endpoint const& ip + , peer_id const& pid, std::string const& msg_) + : peer_alert(h, ip, pid) + , msg(msg_) + {} + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new peer_disconnected_alert(*this)); } + virtual char const* what() const { return "peer disconnected"; } + const static int static_category = alert::debug_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return peer_alert::message() + " disconnecting: " + msg; + } + + std::string msg; + }; + + struct TORRENT_EXPORT invalid_request_alert: peer_alert + { + invalid_request_alert(torrent_handle const& h, tcp::endpoint const& ip + , peer_id const& pid, peer_request const& r) + : peer_alert(h, ip, pid) , request(r) - , pid(pid_) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new invalid_request_alert(*this)); } + virtual char const* what() const { return "invalid piece request"; } + virtual std::string message() const + { + return peer_alert::message() + " peer sent an invalid piece request " + "( piece: " + boost::lexical_cast(request.piece) + + " start: " + boost::lexical_cast(request.start) + + " len: " + boost::lexical_cast(request.length) + ")"; + } - tcp::endpoint ip; peer_request request; - peer_id pid; }; struct TORRENT_EXPORT torrent_finished_alert: torrent_alert { torrent_finished_alert( - const torrent_handle& h - , const std::string& msg) - : torrent_alert(h, alert::warning, msg) + const torrent_handle& h) + : torrent_alert(h) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new torrent_finished_alert(*this)); } + virtual char const* what() const { return "torrent finished"; } + const static int static_category = alert::status_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " torrent finished downloading"; + } }; struct TORRENT_EXPORT piece_finished_alert: torrent_alert { piece_finished_alert( const torrent_handle& h - , int piece_num - , const std::string& msg) - : torrent_alert(h, alert::debug, msg) + , int piece_num) + : torrent_alert(h) , piece_index(piece_num) { TORRENT_ASSERT(piece_index >= 0);} @@ -231,16 +523,73 @@ namespace libtorrent virtual std::auto_ptr clone() const { return std::auto_ptr(new piece_finished_alert(*this)); } + virtual char const* what() const { return "piece finished downloading"; } + const static int static_category = alert::progress_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " piece " + + boost::lexical_cast(piece_index) + " finished downloading"; + } }; - struct TORRENT_EXPORT block_finished_alert: torrent_alert + struct TORRENT_EXPORT request_dropped_alert: peer_alert { - block_finished_alert( - const torrent_handle& h - , int block_num - , int piece_num - , const std::string& msg) - : torrent_alert(h, alert::debug, msg) + request_dropped_alert(const torrent_handle& h, tcp::endpoint const& ip + , peer_id const& pid, int block_num, int piece_num) + : peer_alert(h, ip, pid) + , block_index(block_num) + , piece_index(piece_num) + { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} + + int block_index; + int piece_index; + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new request_dropped_alert(*this)); } + virtual char const* what() const { return "block request dropped"; } + const static int static_category = alert::progress_notification + | alert::peer_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return peer_alert::message() + " peer dropped block ( piece: " + + boost::lexical_cast(piece_index) + " block: " + + boost::lexical_cast(block_index) + ")"; + } + }; + + struct TORRENT_EXPORT block_timeout_alert: peer_alert + { + block_timeout_alert(const torrent_handle& h, tcp::endpoint const& ip + , peer_id const& pid, int block_num, int piece_num) + : peer_alert(h, ip, pid) + , block_index(block_num) + , piece_index(piece_num) + { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} + + int block_index; + int piece_index; + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new block_timeout_alert(*this)); } + virtual char const* what() const { return "block timed out"; } + const static int static_category = alert::progress_notification + | alert::peer_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return peer_alert::message() + " peer timed out request ( piece: " + + boost::lexical_cast(piece_index) + " block: " + + boost::lexical_cast(block_index) + ")"; + } + }; + + struct TORRENT_EXPORT block_finished_alert: peer_alert + { + block_finished_alert(const torrent_handle& h, tcp::endpoint const& ip + , peer_id const& pid, int block_num, int piece_num) + : peer_alert(h, ip, pid) , block_index(block_num) , piece_index(piece_num) { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} @@ -250,68 +599,220 @@ namespace libtorrent virtual std::auto_ptr clone() const { return std::auto_ptr(new block_finished_alert(*this)); } + virtual char const* what() const { return "block finished downloading"; } + const static int static_category = alert::progress_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return peer_alert::message() + " block finished downloading ( piece: " + + boost::lexical_cast(piece_index) + " block: " + + boost::lexical_cast(block_index) + ")"; + } }; - struct TORRENT_EXPORT block_downloading_alert: torrent_alert + struct TORRENT_EXPORT block_downloading_alert: peer_alert { - block_downloading_alert( - const torrent_handle& h - , char const* speedmsg - , int block_num - , int piece_num - , const std::string& msg) - : torrent_alert(h, alert::debug, msg) + block_downloading_alert(const torrent_handle& h, tcp::endpoint const& ip + , peer_id const& pid, char const* speedmsg, int block_num, int piece_num) + : peer_alert(h, ip, pid) , peer_speedmsg(speedmsg) , block_index(block_num) , piece_index(piece_num) { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} - std::string peer_speedmsg; + char const* peer_speedmsg; int block_index; int piece_index; virtual std::auto_ptr clone() const { return std::auto_ptr(new block_downloading_alert(*this)); } + virtual char const* what() const { return "block requested"; } + const static int static_category = alert::progress_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return peer_alert::message() + " requested block ( piece: " + + boost::lexical_cast(piece_index) + " block: " + + boost::lexical_cast(block_index) + ") " + + peer_speedmsg; + } + }; + + struct TORRENT_EXPORT unwanted_block_alert: peer_alert + { + unwanted_block_alert(const torrent_handle& h, tcp::endpoint const& ip + , peer_id const& pid, int block_num, int piece_num) + : peer_alert(h, ip, pid) + , block_index(block_num) + , piece_index(piece_num) + { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} + + int block_index; + int piece_index; + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new unwanted_block_alert(*this)); } + virtual char const* what() const { return "unwanted block received"; } + virtual std::string message() const + { + return peer_alert::message() + " received block not in download queue ( piece: " + + boost::lexical_cast(piece_index) + " block: " + + boost::lexical_cast(block_index) + ")"; + } }; struct TORRENT_EXPORT storage_moved_alert: torrent_alert { - storage_moved_alert(torrent_handle const& h, std::string const& path) - : torrent_alert(h, alert::warning, path) + storage_moved_alert(torrent_handle const& h, std::string const& path_) + : torrent_alert(h) + , path(path_) {} + std::string path; + virtual std::auto_ptr clone() const { return std::auto_ptr(new storage_moved_alert(*this)); } + virtual char const* what() const { return "storage moved"; } + const static int static_category = alert::storage_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " moved storage to: " + + path; + } }; struct TORRENT_EXPORT torrent_deleted_alert: torrent_alert { - torrent_deleted_alert(torrent_handle const& h, std::string const& msg) - : torrent_alert(h, alert::warning, msg) + torrent_deleted_alert(torrent_handle const& h) + : torrent_alert(h) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new torrent_deleted_alert(*this)); } + virtual char const* what() const { return "torrent deleted"; } + const static int static_category = alert::storage_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " deleted"; + } + }; + + struct TORRENT_EXPORT torrent_delete_failed_alert: torrent_alert + { + torrent_delete_failed_alert(torrent_handle const& h, std::string msg_) + : torrent_alert(h) + , msg(msg_) + {} + + std::string msg; + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new torrent_delete_failed_alert(*this)); } + virtual char const* what() const { return "torrent delete failed"; } + const static int static_category = alert::storage_notification + | alert::error_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " torrent deletion failed: " + + msg; + } + }; + + struct TORRENT_EXPORT save_resume_data_alert: torrent_alert + { + save_resume_data_alert(boost::shared_ptr const& rd + , torrent_handle const& h) + : torrent_alert(h) + , resume_data(rd) + {} + + boost::shared_ptr resume_data; + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new save_resume_data_alert(*this)); } + virtual char const* what() const { return "save resume data complete"; } + const static int static_category = alert::storage_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " resume data generated"; + } + }; + + struct TORRENT_EXPORT save_resume_data_failed_alert: torrent_alert + { + save_resume_data_failed_alert(torrent_handle const& h + , std::string const& msg_) + : torrent_alert(h) + , msg(msg_) + {} + + std::string msg; + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new save_resume_data_failed_alert(*this)); } + virtual char const* what() const { return "save resume data failed"; } + const static int static_category = alert::storage_notification + | alert::error_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " resume data was not generated: " + + msg; + } }; struct TORRENT_EXPORT torrent_paused_alert: torrent_alert { - torrent_paused_alert(torrent_handle const& h, std::string const& msg) - : torrent_alert(h, alert::warning, msg) + torrent_paused_alert(torrent_handle const& h) + : torrent_alert(h) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new torrent_paused_alert(*this)); } + virtual char const* what() const { return "torrent paused"; } + const static int static_category = alert::status_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " paused"; + } + }; + + struct TORRENT_EXPORT torrent_resumed_alert: torrent_alert + { + torrent_resumed_alert(torrent_handle const& h) + : torrent_alert(h) {} + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new torrent_resumed_alert(*this)); } + virtual char const* what() const { return "torrent resumed"; } + const static int static_category = alert::status_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " resumed"; + } }; struct TORRENT_EXPORT torrent_checked_alert: torrent_alert { - torrent_checked_alert(torrent_handle const& h, std::string const& msg) - : torrent_alert(h, alert::info, msg) + torrent_checked_alert(torrent_handle const& h) + : torrent_alert(h) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new torrent_checked_alert(*this)); } + virtual char const* what() const { return "torrent checked"; } + const static int static_category = alert::status_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " checked"; + } }; @@ -320,128 +821,269 @@ namespace libtorrent url_seed_alert( torrent_handle const& h , const std::string& url_ - , const std::string& msg) - : torrent_alert(h, alert::warning, msg) + , const std::string& msg_) + : torrent_alert(h) , url(url_) + , msg(msg_) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new url_seed_alert(*this)); } + virtual char const* what() const { return "web seed error"; } + const static int static_category = alert::peer_notification | alert::error_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " url seed (" + + url + ") failed: " + msg; + } std::string url; + std::string msg; }; struct TORRENT_EXPORT file_error_alert: torrent_alert { file_error_alert( - const torrent_handle& h - , const std::string& msg) - : torrent_alert(h, alert::fatal, msg) + std::string const& f + , const torrent_handle& h + , const std::string& msg_) + : torrent_alert(h) + , file(f) + , msg(msg_) {} + std::string file; + std::string msg; + virtual std::auto_ptr clone() const { return std::auto_ptr(new file_error_alert(*this)); } + virtual char const* what() const { return "file error"; } + const static int static_category = alert::status_notification + | alert::error_notification + | alert::storage_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " file (" + file + ") error: " + + msg; + } }; struct TORRENT_EXPORT metadata_failed_alert: torrent_alert { - metadata_failed_alert( - const torrent_handle& h - , const std::string& msg) - : torrent_alert(h, alert::info, msg) + metadata_failed_alert(const torrent_handle& h) + : torrent_alert(h) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new metadata_failed_alert(*this)); } + virtual char const* what() const { return "metadata failed"; } + const static int static_category = alert::error_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " invalid metadata received"; + } }; struct TORRENT_EXPORT metadata_received_alert: torrent_alert { metadata_received_alert( - const torrent_handle& h - , const std::string& msg) - : torrent_alert(h, alert::info, msg) + const torrent_handle& h) + : torrent_alert(h) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new metadata_received_alert(*this)); } + virtual char const* what() const { return "metadata received"; } + const static int static_category = alert::status_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " metadata successfully received"; + } + }; + + struct TORRENT_EXPORT udp_error_alert: alert + { + udp_error_alert( + udp::endpoint const& ep + , error_code const& ec) + : endpoint(ep) + , error(ec) + {} + + udp::endpoint endpoint; + error_code error; + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new udp_error_alert(*this)); } + virtual char const* what() const { return "udp error"; } + const static int static_category = alert::error_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + error_code ec; + return "UDP error: " + error.message() + " from: " + endpoint.address().to_string(ec); + } + }; + + struct TORRENT_EXPORT external_ip_alert: alert + { + external_ip_alert(address const& ip) + : external_address(ip) + {} + + address external_address; + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new external_ip_alert(*this)); } + virtual char const* what() const { return "external IP received"; } + const static int static_category = alert::status_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + error_code ec; + return "external IP received: " + external_address.to_string(ec); + } }; struct TORRENT_EXPORT listen_failed_alert: alert { listen_failed_alert( tcp::endpoint const& ep - , std::string const& msg) - : alert(alert::fatal, msg) - , endpoint(ep) + , error_code const& ec) + : endpoint(ep) + , error(ec) {} tcp::endpoint endpoint; + error_code error; virtual std::auto_ptr clone() const { return std::auto_ptr(new listen_failed_alert(*this)); } + virtual char const* what() const { return "listen failed"; } + const static int static_category = alert::status_notification | alert::error_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + error_code ec; + return "listening on " + endpoint.address().to_string(ec) + ":" + + boost::lexical_cast(endpoint.port()) + " failed: " + + error.message(); + } }; struct TORRENT_EXPORT listen_succeeded_alert: alert { - listen_succeeded_alert( - tcp::endpoint const& ep - , std::string const& msg) - : alert(alert::fatal, msg) - , endpoint(ep) + listen_succeeded_alert(tcp::endpoint const& ep) + : endpoint(ep) {} tcp::endpoint endpoint; virtual std::auto_ptr clone() const { return std::auto_ptr(new listen_succeeded_alert(*this)); } + virtual char const* what() const { return "listen succeeded"; } + const static int static_category = alert::status_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + error_code ec; + return "successfully listening on " + endpoint.address().to_string(ec) + + ":" + boost::lexical_cast(endpoint.port()); + } }; struct TORRENT_EXPORT portmap_error_alert: alert { - portmap_error_alert(const std::string& msg) - : alert(alert::warning, msg) + portmap_error_alert(int i, int t, const std::string& msg_) + : mapping(i), type(t), msg(msg_) {} + int mapping; + int type; + std::string msg; + virtual std::auto_ptr clone() const { return std::auto_ptr(new portmap_error_alert(*this)); } + virtual char const* what() const { return "port map error"; } + const static int static_category = alert::port_mapping_notification + | alert::error_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + static char const* type_str[] = {"NAT-PMP", "UPnP"}; + return std::string("could not map port using ") + type_str[type] + + ": " + msg; + } }; struct TORRENT_EXPORT portmap_alert: alert { - portmap_alert(const std::string& msg) - : alert(alert::info, msg) + portmap_alert(int i, int port, int t) + : mapping(i), external_port(port), type(t) {} + int mapping; + int external_port; + int type; + virtual std::auto_ptr clone() const { return std::auto_ptr(new portmap_alert(*this)); } + virtual char const* what() const { return "port map succeeded"; } + const static int static_category = alert::port_mapping_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + static char const* type_str[] = {"NAT-PMP", "UPnP"}; + return std::string("successfully mapped port using ") + type_str[type] + + ". external port: " + boost::lexical_cast(external_port); + } }; struct TORRENT_EXPORT fastresume_rejected_alert: torrent_alert { fastresume_rejected_alert(torrent_handle const& h - , std::string const& msg) - : torrent_alert(h, alert::warning, msg) + , std::string const& msg_) + : torrent_alert(h) + , msg(msg_) {} + std::string msg; + virtual std::auto_ptr clone() const { return std::auto_ptr(new fastresume_rejected_alert(*this)); } + virtual char const* what() const { return "resume data rejected"; } + const static int static_category = alert::status_notification + | alert::error_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + return torrent_alert::message() + " fast resume rejected: " + msg; + } }; struct TORRENT_EXPORT peer_blocked_alert: alert { - peer_blocked_alert(address const& ip_ - , std::string const& msg) - : alert(alert::info, msg) - , ip(ip_) + peer_blocked_alert(address const& ip_) + : ip(ip_) {} address ip; virtual std::auto_ptr clone() const { return std::auto_ptr(new peer_blocked_alert(*this)); } + virtual char const* what() const { return "peer blocked"; } + const static int static_category = alert::ip_block_notification; + virtual int category() const { return static_category; } + virtual std::string message() const + { + error_code ec; + return "blocked peer: " + ip.to_string(ec); + } }; - } diff --git a/libtorrent/include/libtorrent/asio/basic_resolver.hpp b/libtorrent/include/libtorrent/asio/basic_resolver.hpp deleted file mode 100644 index 5df89d545..000000000 --- a/libtorrent/include/libtorrent/asio/basic_resolver.hpp +++ /dev/null @@ -1,252 +0,0 @@ -// -// basic_resolver.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_BASIC_RESOLVER_HPP -#define ASIO_BASIC_RESOLVER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/basic_io_object.hpp" -#include "asio/error.hpp" -#include "asio/error_handler.hpp" -#include "asio/resolver_service.hpp" - -namespace asio { - -/// Provides endpoint resolution functionality. -/** - * The basic_resolver class template provides the ability to resolve a query - * to a list of endpoints. - * - * @par Thread Safety: - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * Async_Object, Error_Source. - */ -template > -class basic_resolver - : public basic_io_object -{ -public: - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// The query type. - typedef typename Protocol::resolver_query query; - - /// The iterator type. - typedef typename Protocol::resolver_iterator iterator; - - /// The type used for reporting errors. - typedef asio::error error_type; - - /// Constructor. - /** - * This constructor creates a basic_resolver. - * - * @param io_service The io_service object that the resolver will use to - * dispatch handlers for any asynchronous operations performed on the timer. - */ - explicit basic_resolver(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Cancel any asynchronous operations that are waiting on the resolver. - /** - * This function forces the completion of any pending asynchronous - * operations on the host resolver. The handler for each cancelled operation - * will be invoked with the asio::error::operation_aborted error code. - */ - void cancel() - { - return this->service.cancel(this->implementation); - } - - /// Resolve a query to a list of entries. - /** - * This function is used to resolve a query into a list of endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. - * - * @throws asio::error Thrown on failure. - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful call to this function is guaranteed to return at least - * one entry. - */ - iterator resolve(const query& q) - { - return this->service.resolve(this->implementation, q, throw_error()); - } - - /// Resolve a query to a list of entries. - /** - * This function is used to resolve a query into a list of endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. Returns a default constructed iterator if an error - * occurs. - * - * @param error_handler A handler to be called when the operation completes, - * to indicate whether or not an error has occurred. Copies will be made of - * the handler as required. The function signature of the handler must be: - * @code void error_handler( - * const asio::error& error // Result of operation. - * ); @endcode - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful call to this function is guaranteed to return at least - * one entry. - */ - template - iterator resolve(const query& q, Error_Handler error_handler) - { - return this->service.resolve(this->implementation, q, error_handler); - } - - /// Asynchronously resolve a query to a list of entries. - /** - * This function is used to asynchronously resolve a query into a list of - * endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error& error, // Result of operation. - * resolver::iterator iterator // Forward-only iterator that can be used to - * // traverse the list of endpoint entries. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful resolve operation is guaranteed to pass at least one - * entry to the handler. - */ - template - void async_resolve(const query& q, Handler handler) - { - return this->service.async_resolve(this->implementation, q, handler); - } - - /// Resolve an endpoint to a list of entries. - /** - * This function is used to resolve an endpoint into a list of endpoint - * entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. - * - * @throws asio::error Thrown on failure. - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful call to this function is guaranteed to return at least - * one entry. - */ - iterator resolve(const endpoint_type& e) - { - return this->service.resolve(this->implementation, e, throw_error()); - } - - /// Resolve an endpoint to a list of entries. - /** - * This function is used to resolve an endpoint into a list of endpoint - * entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. Returns a default constructed iterator if an error - * occurs. - * - * @param error_handler A handler to be called when the operation completes, - * to indicate whether or not an error has occurred. Copies will be made of - * the handler as required. The function signature of the handler must be: - * @code void error_handler( - * const asio::error& error // Result of operation. - * ); @endcode - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful call to this function is guaranteed to return at least - * one entry. - */ - template - iterator resolve(const endpoint_type& e, Error_Handler error_handler) - { - return this->service.resolve(this->implementation, e, error_handler); - } - - /// Asynchronously resolve an endpoint to a list of entries. - /** - * This function is used to asynchronously resolve an endpoint into a list of - * endpoint entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error& error, // Result of operation. - * resolver::iterator iterator // Forward-only iterator that can be used to - * // traverse the list of endpoint entries. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful resolve operation is guaranteed to pass at least one - * entry to the handler. - */ - template - void async_resolve(const endpoint_type& e, Handler handler) - { - return this->service.async_resolve(this->implementation, e, handler); - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_RESOLVER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_iocp_operation.hpp b/libtorrent/include/libtorrent/asio/detail/win_iocp_operation.hpp deleted file mode 100644 index 34b0fad90..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_iocp_operation.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// -// win_iocp_operation.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_IOCP_OPERATION_HPP -#define ASIO_DETAIL_WIN_IOCP_OPERATION_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/win_iocp_io_service_fwd.hpp" - -#if defined(ASIO_HAS_IOCP) - -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -// Base class for all IOCP operations. A function pointer is used instead of -// virtual functions to avoid the associated overhead. -// -// This class inherits from OVERLAPPED so that we can downcast to get back to -// the win_iocp_operation pointer from the LPOVERLAPPED out parameter of -// GetQueuedCompletionStatus. -struct win_iocp_operation - : public OVERLAPPED -{ - typedef void (*invoke_func_type)(win_iocp_operation*, DWORD, size_t); - typedef void (*destroy_func_type)(win_iocp_operation*); - - win_iocp_operation(invoke_func_type invoke_func, - destroy_func_type destroy_func) - : invoke_func_(invoke_func), - destroy_func_(destroy_func) - { - Internal = 0; - InternalHigh = 0; - Offset = 0; - OffsetHigh = 0; - hEvent = 0; - } - - void do_completion(DWORD last_error, size_t bytes_transferred) - { - invoke_func_(this, last_error, bytes_transferred); - } - - void destroy() - { - destroy_func_(this); - } - -protected: - // Prevent deletion through this type. - ~win_iocp_operation() - { - } - -private: - invoke_func_type invoke_func_; - destroy_func_type destroy_func_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_IOCP) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_IOCP_OPERATION_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_local_free_on_block_exit.hpp b/libtorrent/include/libtorrent/asio/detail/win_local_free_on_block_exit.hpp deleted file mode 100644 index c909e1af3..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_local_free_on_block_exit.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// win_local_free_on_block_exit.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_LOCAL_FREE_ON_BLOCK_EXIT_HPP -#define ASIO_DETAIL_WIN_LOCAL_FREE_ON_BLOCK_EXIT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -class win_local_free_on_block_exit - : private noncopyable -{ -public: - // Constructor blocks all signals for the calling thread. - explicit win_local_free_on_block_exit(void* p) - : p_(p) - { - } - - // Destructor restores the previous signal mask. - ~win_local_free_on_block_exit() - { - ::LocalFree(p_); - } - -private: - void* p_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_LOCAL_FREE_ON_BLOCK_EXIT_HPP diff --git a/libtorrent/include/libtorrent/asio/error_handler.hpp b/libtorrent/include/libtorrent/asio/error_handler.hpp deleted file mode 100644 index c315c8d5e..000000000 --- a/libtorrent/include/libtorrent/asio/error_handler.hpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// error_handler.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_ERROR_HANDLER_HPP -#define ASIO_ERROR_HANDLER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { - -namespace detail { - -class ignore_error_t -{ -public: - typedef void result_type; - - template - void operator()(const Error&) const - { - } -}; - -class throw_error_t -{ -public: - typedef void result_type; - - template - void operator()(const Error& err) const - { - if (err) - boost::throw_exception(err); - } -}; - -template -class assign_error_t -{ -public: - typedef void result_type; - - assign_error_t(Target& target) - : target_(&target) - { - } - - template - void operator()(const Error& err) const - { - *target_ = err; - } - -private: - Target* target_; -}; - -} // namespace detail - -/** - * @defgroup error_handler Error Handler Function Objects - * - * Function objects for custom error handling. - */ -/*@{*/ - -/// Return a function object that always ignores the error. -#if defined(GENERATING_DOCUMENTATION) -unspecified ignore_error(); -#else -inline detail::ignore_error_t ignore_error() -{ - return detail::ignore_error_t(); -} -#endif - -/// Return a function object that always throws the error. -#if defined(GENERATING_DOCUMENTATION) -unspecified throw_error(); -#else -inline detail::throw_error_t throw_error() -{ - return detail::throw_error_t(); -} -#endif - -/// Return a function object that assigns the error to a variable. -#if defined(GENERATING_DOCUMENTATION) -template -unspecified assign_error(Target& target); -#else -template -inline detail::assign_error_t assign_error(Target& target) -{ - return detail::assign_error_t(target); -} -#endif - -/*@}*/ - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_ERROR_HANDLER_HPP diff --git a/libtorrent/include/libtorrent/asio/read_until.hpp b/libtorrent/include/libtorrent/asio/read_until.hpp deleted file mode 100644 index 8c7e3d379..000000000 --- a/libtorrent/include/libtorrent/asio/read_until.hpp +++ /dev/null @@ -1,452 +0,0 @@ -// -// read_until.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_READ_UNTIL_HPP -#define ASIO_READ_UNTIL_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_streambuf.hpp" -#include "asio/error.hpp" - -namespace asio { - -/** - * @defgroup read_until asio::read_until - */ -/*@{*/ - -/// Read data into a streambuf until a delimiter is encountered. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter character. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * asio::read_until(s, b, '\n'); - * std::istream is(&b); - * std::string line; - * std::getline(is, line); @endcode - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, char delim); - -/// Read data into a streambuf until a delimiter is encountered. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter character. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. Returns 0 if an error occurred. - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, char delim, - asio::error_code& ec); - -/// Read data into a streambuf until a delimiter is encountered. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter string. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * asio::read_until(s, b, "\r\n"); - * std::istream is(&b); - * std::string line; - * std::getline(is, line); @endcode - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim); - -/// Read data into a streambuf until a delimiter is encountered. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter string. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. Returns 0 if an error occurred. - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim, - asio::error_code& ec); - -/// Read data into a streambuf until a regular expression is located. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains some data that matches a regular expression. - * The call will block until one of the following conditions is true: - * - * @li A substring of the streambuf's get area matches the regular expression. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains data that - * matches the regular expression, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param expr The regular expression. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the substring that matches the regular expression. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read data into a streambuf until a CR-LF sequence is encountered: - * @code asio::streambuf b; - * asio::read_until(s, b, boost::regex("\r\n")); - * std::istream is(&b); - * std::string line; - * std::getline(is, line); @endcode - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr); - -/// Read data into a streambuf until a regular expression is located. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains some data that matches a regular expression. - * The call will block until one of the following conditions is true: - * - * @li A substring of the streambuf's get area matches the regular expression. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains data that - * matches the regular expression, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param expr The regular expression. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the substring that matches the regular expression. Returns 0 if an error - * occurred. - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr, - asio::error_code& ec); - -/*@}*/ -/** -* @defgroup async_read_until asio::async_read_until -*/ -/*@{*/ - -/// Start an asynchronous operation to read data into a streambuf until a -/// delimiter is encountered. -/** - * This function is used to asynchronously read data into the specified - * streambuf until the streambuf's get area contains the specified delimiter. - * The function call always returns immediately. The asynchronous operation - * will continue until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains the - * delimiter, the asynchronous operation completes immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. Ownership of - * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. - * - * @param delim The delimiter character. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // The number of bytes in the - * // streambuf's get area up to - * // and including the delimiter. - * // 0 if an error occurred. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To asynchronously read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * ... - * void handler(const asio::error_code& e, std::size_t size) - * { - * if (!e) - * { - * std::istream is(&b); - * std::string line; - * std::getline(is, line); - * ... - * } - * } - * ... - * asio::async_read_until(s, b, '\n', handler); @endcode - */ -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, - char delim, ReadHandler handler); - -/// Start an asynchronous operation to read data into a streambuf until a -/// delimiter is encountered. -/** - * This function is used to asynchronously read data into the specified - * streambuf until the streambuf's get area contains the specified delimiter. - * The function call always returns immediately. The asynchronous operation - * will continue until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains the - * delimiter, the asynchronous operation completes immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. Ownership of - * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. - * - * @param delim The delimiter string. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // The number of bytes in the - * // streambuf's get area up to - * // and including the delimiter. - * // 0 if an error occurred. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To asynchronously read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * ... - * void handler(const asio::error_code& e, std::size_t size) - * { - * if (!e) - * { - * std::istream is(&b); - * std::string line; - * std::getline(is, line); - * ... - * } - * } - * ... - * asio::async_read_until(s, b, "\r\n", handler); @endcode - */ -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim, - ReadHandler handler); - -/// Start an asynchronous operation to read data into a streambuf until a -/// regular expression is located. -/** - * This function is used to asynchronously read data into the specified - * streambuf until the streambuf's get area contains some data that matches a - * regular expression. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: - * - * @li A substring of the streambuf's get area matches the regular expression. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains data - * that matches the regular expression, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. Ownership of - * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. - * - * @param expr The regular expression. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // The number of bytes in the - * // streambuf's get area up to - * // and including the substring - * // that matches the regular. - * // expression. 0 if an error - * // occurred. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To asynchronously read data into a streambuf until a CR-LF sequence is - * encountered: - * @code asio::streambuf b; - * ... - * void handler(const asio::error_code& e, std::size_t size) - * { - * if (!e) - * { - * std::istream is(&b); - * std::string line; - * std::getline(is, line); - * ... - * } - * } - * ... - * asio::async_read_until(s, b, boost::regex("\r\n"), handler); @endcode - */ -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr, - ReadHandler handler); - -/*@}*/ - -} // namespace asio - -#include "asio/impl/read_until.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_READ_UNTIL_HPP diff --git a/libtorrent/include/libtorrent/asio/resolver_service.hpp b/libtorrent/include/libtorrent/asio/resolver_service.hpp deleted file mode 100644 index bdd8dbfbd..000000000 --- a/libtorrent/include/libtorrent/asio/resolver_service.hpp +++ /dev/null @@ -1,126 +0,0 @@ -// -// resolver_service.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_RESOLVER_SERVICE_HPP -#define ASIO_RESOLVER_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/resolver_service.hpp" - -namespace asio { - -/// Default service implementation for a resolver. -template -class resolver_service - : public asio::io_service::service -{ -public: - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// The query type. - typedef typename Protocol::resolver_query query_type; - - /// The iterator type. - typedef typename Protocol::resolver_iterator iterator_type; - -private: - // The type of the platform-specific implementation. - typedef detail::resolver_service service_impl_type; - -public: - /// The type of a resolver implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// Construct a new resolver service for the specified io_service. - explicit resolver_service(asio::io_service& io_service) - : asio::io_service::service(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new resolver implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a resolver implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Cancel pending asynchronous operations. - void cancel(implementation_type& impl) - { - service_impl_.cancel(impl); - } - - /// Resolve a query to a list of entries. - template - iterator_type resolve(implementation_type& impl, const query_type& query, - Error_Handler error_handler) - { - return service_impl_.resolve(impl, query, error_handler); - } - - /// Asynchronously resolve a query to a list of entries. - template - void async_resolve(implementation_type& impl, const query_type& query, - Handler handler) - { - service_impl_.async_resolve(impl, query, handler); - } - - /// Resolve an endpoint to a list of entries. - template - iterator_type resolve(implementation_type& impl, - const endpoint_type& endpoint, Error_Handler error_handler) - { - return service_impl_.resolve(impl, endpoint, error_handler); - } - - /// Asynchronously resolve an endpoint to a list of entries. - template - void async_resolve(implementation_type& impl, const endpoint_type& endpoint, - Handler handler) - { - return service_impl_.async_resolve(impl, endpoint, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_RESOLVER_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/system_exception.hpp b/libtorrent/include/libtorrent/asio/system_exception.hpp deleted file mode 100644 index 599e22712..000000000 --- a/libtorrent/include/libtorrent/asio/system_exception.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// -// error.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SYSTEM_EXCEPTION_HPP -#define ASIO_SYSTEM_EXCEPTION_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -# include -#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/win_local_free_on_block_exit.hpp" - -namespace asio { - -/// The system_exception class is used to represent system conditions that -/// prevent the library from operating correctly. -class system_exception - : public std::exception -{ -public: - /// Construct with a specific context and error code. - system_exception(const std::string& context, int code) - : context_(context), - code_(code) - { - } - - /// Copy constructor. - system_exception(const system_exception& e) - : std::exception(e), - context_(e.context_), - code_(e.code_) - { - } - - /// Destructor. - virtual ~system_exception() throw () - { - } - - /// Assignment operator. - system_exception& operator=(const system_exception& e) - { - context_ = e.context_; - code_ = e.code_; - what_.reset(); - return *this; - } - - /// Get a string representation of the exception. - virtual const char* what() const throw () - { -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - try - { - if (!what_) - { - char* msg = 0; - DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS, 0, code_, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); - detail::win_local_free_on_block_exit local_free_obj(msg); - if (length && msg[length - 1] == '\n') - msg[--length] = '\0'; - if (length && msg[length - 1] == '\r') - msg[--length] = '\0'; - if (length) - { - std::string tmp(context_); - tmp += ": "; - tmp += msg; - what_.reset(new std::string(tmp)); - } - else - { - return "asio system_exception"; - } - } - return what_->c_str(); - } - catch (std::exception&) - { - return "asio system_exception"; - } -#elif defined(__sun) || defined(__QNX__) - return strerror(code_); -#elif defined(__MACH__) && defined(__APPLE__) \ - || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) - try - { - char buf[256] = ""; - strerror_r(code_, buf, sizeof(buf)); - std::string tmp(context_); - tmp += ": "; - tmp += buf; - what_.reset(new std::string(tmp)); - return what_->c_str(); - } - catch (std::exception&) - { - return "asio system_exception"; - } -#else - try - { - char buf[256] = ""; - std::string tmp(context_); - tmp += ": "; - tmp += strerror_r(code_, buf, sizeof(buf)); - what_.reset(new std::string(tmp)); - return what_->c_str(); - } - catch (std::exception&) - { - return "asio system_exception"; - } -#endif - } - - /// Get the implementation-defined context associated with the exception. - const std::string& context() const - { - return context_; - } - - /// Get the implementation-defined code associated with the exception. - int code() const - { - return code_; - } - -private: - // The context associated with the error. - std::string context_; - - // The code associated with the error. - int code_; - - // The string representation of the error. - mutable boost::scoped_ptr what_; -}; - -/// Output the string associated with a system exception. -/** - * Used to output a human-readable string that is associated with a system - * exception. - * - * @param os The output stream to which the string will be written. - * - * @param e The exception to be written. - * - * @return The output stream. - * - * @relates asio::system_exception - */ -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -std::ostream& operator<<(std::ostream& os, const system_exception& e) -{ - os << e.what(); - return os; -} -#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -template -Ostream& operator<<(Ostream& os, const system_exception& e) -{ - os << e.what(); - return os; -} -#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SYSTEM_EXCEPTION_HPP diff --git a/libtorrent/include/libtorrent/assert.hpp b/libtorrent/include/libtorrent/assert.hpp index dd3c6b737..6943fadc2 100644 --- a/libtorrent/include/libtorrent/assert.hpp +++ b/libtorrent/include/libtorrent/assert.hpp @@ -33,7 +33,11 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef TORRENT_ASSERT #include "libtorrent/config.hpp" -#include +#include + +#ifdef __GNUC__ +std::string demangle(char const* name); +#endif #if (defined __linux__ || defined __MACH__) && defined __GNUC__ && !defined(NDEBUG) diff --git a/libtorrent/include/libtorrent/aux_/allocate_resources_impl.hpp b/libtorrent/include/libtorrent/aux_/allocate_resources_impl.hpp deleted file mode 100644 index 31865d40a..000000000 --- a/libtorrent/include/libtorrent/aux_/allocate_resources_impl.hpp +++ /dev/null @@ -1,328 +0,0 @@ -/* - -Copyright (c) 2003, Magnus Jonsson -All rights reserved. - -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. - -*/ - -#ifndef TORRENT_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED -#define TORRENT_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED - -#include -#include - -#include - -#include "libtorrent/resource_request.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/size_type.hpp" - -#ifdef min -#undef min -#endif - -#ifdef max -#undef max -#endif - -namespace libtorrent -{ - - int saturated_add(int a, int b); - - namespace aux - { - // give num_resources to r, - // return how how many were actually accepted. - inline int give(resource_request& r, int num_resources) - { - assert(num_resources >= 0); - assert(r.given <= r.max); - - int accepted = (std::min)(num_resources, r.max - r.given); - assert(accepted >= 0); - - r.given += accepted; - assert(r.given <= r.max); - - return accepted; - } - - inline int div_round_up(int numerator, int denominator) - { - return (numerator + denominator - 1) / denominator; - } - -#ifndef NDEBUG - - template - class allocate_resources_contract_check - { - int m_resources; - It m_start; - It m_end; - resource_request T::* m_res; - - public: - allocate_resources_contract_check( - int resources - , It start - , It end - , resource_request T::* res) - : m_resources(resources) - , m_start(start) - , m_end(end) - , m_res(res) - { - assert(m_resources >= 0); - for (It i = m_start, end(m_end); i != end; ++i) - { - assert(((*i).*m_res).max >= 0); - assert(((*i).*m_res).given >= 0); - } - } - - ~allocate_resources_contract_check() - { - int sum_given = 0; - int sum_max = 0; - int sum_min = 0; - for (It i = m_start, end(m_end); i != end; ++i) - { - assert(((*i).*m_res).max >= 0); - assert(((*i).*m_res).min >= 0); - assert(((*i).*m_res).max >= ((*i).*m_res).min); - assert(((*i).*m_res).given >= 0); - assert(((*i).*m_res).given <= ((*i).*m_res).max); - - sum_given = saturated_add(sum_given, ((*i).*m_res).given); - sum_max = saturated_add(sum_max, ((*i).*m_res).max); - sum_min = saturated_add(sum_min, ((*i).*m_res).min); - } - if (sum_given != (std::min)(std::max(m_resources, sum_min), sum_max)) - { - std::cerr << sum_given << " " << m_resources << " " << sum_min << " " << sum_max << std::endl; - assert(false); - } - } - }; - -#endif - - template - void allocate_resources_impl( - int resources - , It start - , It end - , resource_request T::* res) - { - assert(resources >= 0); - #ifndef NDEBUG - allocate_resources_contract_check contract_check( - resources - , start - , end - , res); - #endif - - for (It i = start; i != end; ++i) - { - resource_request& r = (*i).*res; - r.leftovers = (std::max)(r.used - r.given, 0); - } - - if (resources == resource_request::inf) - { - // No competition for resources. - // Just give everyone what they want. - for (It i = start; i != end; ++i) - { - ((*i).*res).given = ((*i).*res).max; - } - return; - } - - // Resources are scarce - - int sum_max = 0; - int sum_min = 0; - // the number of consumer that saturated their - // quota last time slice - int num_saturated = 0; - // the total resources that those saturated their - // quota used. This is used to calculate the mean - // of the saturating consumers, in order to - // balance their quotas for the next time slice. - size_type saturated_sum = 0; - for (It i = start; i != end; ++i) - { - resource_request& r = (*i).*res; - sum_max = saturated_add(sum_max, r.max); - assert(r.min < resource_request::inf); - assert(r.min >= 0); - assert(r.min <= r.max); - sum_min += r.min; - - // a consumer that uses 95% or more of its assigned - // quota is considered saturating - size_type used = r.used; - if (r.given == 0) continue; - if (used * 20 / r.given >= 19) - { - ++num_saturated; - saturated_sum += r.given; - } - } - - if (sum_max <= resources) - { - // it turns out that there's no competition for resources - // after all. - for (It i = start; i != end; ++i) - { - ((*i).*res).given = ((*i).*res).max; - } - return; - } - - if (sum_min >= resources) - { - // the amount of resources is smaller than - // the minimum resources to distribute, so - // give everyone the minimum - for (It i = start; i != end; ++i) - { - ((*i).*res).given = ((*i).*res).min; - } - return; - } - - // now, the "used" field will be used as a target value. - // the algorithm following this loop will then scale the - // used values to fit the available resources and store - // the scaled values as given. So, the ratios of the - // used values will be maintained. - for (It i = start; i != end; ++i) - { - resource_request& r = (*i).*res; - - int target; - size_type used = r.used; - if (r.given > 0 && used * 20 / r.given >= 19) - { - assert(num_saturated > 0); - target = div_round_up(saturated_sum, num_saturated); - target += div_round_up(target, 10); - } - else - { - target = r.used; - } - if (target > r.max) target = r.max; - else if (target < r.min) target = r.min; - - // move 12.5% towards the the target value - r.used = r.given + div_round_up(target - r.given, 8); - r.given = r.min; - } - - - resources = (std::max)(resources, sum_min); - int resources_to_distribute = (std::min)(resources, sum_max) - sum_min; - assert(resources_to_distribute >= 0); -#ifndef NDEBUG - int prev_resources_to_distribute = resources_to_distribute; -#endif - while (resources_to_distribute > 0) - { - // in order to scale, we need to calculate the sum of - // all the used values. - size_type total_used = 0; - size_type max_used = 0; - for (It i = start; i != end; ++i) - { - resource_request& r = (*i).*res; - if (r.given == r.max) continue; - - assert(r.given < r.max); - - max_used = (std::max)(max_used, (size_type)r.used + 1); - total_used += (size_type)r.used + 1; - } - - - size_type kNumer = resources_to_distribute; - size_type kDenom = total_used; - assert(kNumer >= 0); - assert(kDenom >= 0); - assert(kNumer <= (std::numeric_limits::max)()); - - if (kNumer * max_used <= kDenom) - { - kNumer = 1; - kDenom = max_used; - assert(kDenom >= 0); - } - - for (It i = start; i != end && resources_to_distribute > 0; ++i) - { - resource_request& r = (*i).*res; - if (r.given == r.max) continue; - - assert(r.given < r.max); - - size_type used = (size_type)r.used + 1; - if (used < 1) used = 1; - size_type to_give = used * kNumer / kDenom; - if (to_give > resources_to_distribute) - to_give = resources_to_distribute; - assert(to_give >= 0); - assert(to_give <= resources_to_distribute); -#ifndef NDEBUG - int tmp = resources_to_distribute; -#endif - resources_to_distribute -= give(r, (int)to_give); - assert(resources_to_distribute <= tmp); - assert(resources_to_distribute >= 0); - } - - assert(resources_to_distribute >= 0); - assert(resources_to_distribute < prev_resources_to_distribute); -#ifndef NDEBUG - prev_resources_to_distribute = resources_to_distribute; -#endif - } - assert(resources_to_distribute == 0); - } - - } // namespace libtorrent::aux -} - - -#endif diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp index 03e9cb619..57da44b4a 100644 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ b/libtorrent/include/libtorrent/aux_/session_impl.hpp @@ -40,6 +40,10 @@ POSSIBILITY OF SUCH DAMAGE. #include #include +#ifndef TORRENT_DISABLE_GEO_IP +#include "libtorrent/GeoIP.h" +#endif + #ifdef _MSC_VER #pragma warning(push, 1) #endif @@ -94,74 +98,7 @@ namespace libtorrent { struct session_impl; - // this data is shared between the main thread and the - // thread that initialize pieces - struct piece_checker_data - { - piece_checker_data() - : processing(false), progress(0.f), abort(false) {} - - boost::shared_ptr torrent_ptr; - fs::path save_path; - - sha1_hash info_hash; - - void parse_resume_data( - const entry& rd - , const torrent_info& info - , std::string& error); - - std::vector piece_map; - std::vector unfinished_pieces; - std::vector block_info; - std::vector peers; - std::vector banned_peers; - entry resume_data; - - // this is true if this torrent is being processed (checked) - // if it is not being processed, then it can be removed from - // the queue without problems, otherwise the abort flag has - // to be set. - bool processing; - - // is filled in by storage::initialize_pieces() - // and represents the progress. It should be a - // value in the range [0, 1] - float progress; - - // abort defaults to false and is typically - // filled in by torrent_handle when the user - // aborts the torrent - bool abort; - }; - - struct checker_impl: boost::noncopyable - { - checker_impl(session_impl& s): m_ses(s), m_abort(false) {} - void operator()(); - piece_checker_data* find_torrent(const sha1_hash& info_hash); - void remove_torrent(sha1_hash const& info_hash, int options); - -#ifndef NDEBUG - void check_invariant() const; -#endif - - // when the files has been checked - // the torrent is added to the session - session_impl& m_ses; - - mutable boost::mutex m_mutex; - boost::condition m_cond; - - // a list of all torrents that are currently in queue - // or checking their files - std::deque > m_torrents; - std::deque > m_processing; - - bool m_abort; - }; - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING struct tracker_logger; #endif @@ -185,7 +122,7 @@ namespace libtorrent std::pair listen_port_range , fingerprint const& cl_fprint , char const* listen_interface -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , fs::path const& logpath #endif ); @@ -194,10 +131,18 @@ namespace libtorrent #ifndef TORRENT_DISABLE_EXTENSIONS void add_extension(boost::function( torrent*, void*)> ext); +#endif +#ifndef NDEBUG + bool has_peer(peer_connection const* p) const + { + return std::find_if(m_connections.begin(), m_connections.end() + , boost::bind(&boost::intrusive_ptr::get, _1) == p) + != m_connections.end(); + } #endif void operator()(); - void open_listen_port() throw(); + void open_listen_port(); // if we are listening on an IPv6 interface // this will return one of the IPv6 addresses on this @@ -206,7 +151,7 @@ namespace libtorrent void async_accept(boost::shared_ptr const& listener); void on_incoming_connection(boost::shared_ptr const& s - , boost::weak_ptr listener, asio::error_code const& e); + , boost::weak_ptr listener, error_code const& e); // must be locked to access the data // in this struct @@ -216,9 +161,8 @@ namespace libtorrent boost::weak_ptr find_torrent(const sha1_hash& info_hash); peer_id const& get_peer_id() const { return m_peer_id; } - void close_connection(boost::intrusive_ptr const& p); - void connection_failed(boost::intrusive_ptr const& p - , tcp::endpoint const& a, char const* message); + void close_connection(peer_connection const* p + , char const* message); void set_settings(session_settings const& s); session_settings const& settings() const { return m_settings; } @@ -241,9 +185,14 @@ namespace libtorrent // called when a port mapping is successful, or a router returns // a failure to map a port - void on_port_mapping(int tcp_port, int udp_port, std::string const& errmsg); + void on_port_mapping(int mapping, int port, std::string const& errmsg + , int nat_transport); bool is_aborted() const { return m_abort; } + bool is_paused() const { return m_paused; } + + void pause(); + void resume(); void set_ip_filter(ip_filter const& f); void set_port_filter(port_filter const& f); @@ -253,31 +202,16 @@ namespace libtorrent , const char* net_interface = 0); bool is_listening() const; - torrent_handle add_torrent( - boost::intrusive_ptr ti - , fs::path const& save_path - , entry const& resume_data - , storage_mode_t storage_mode - , storage_constructor_type sc - , bool paused - , void* userdata); - - torrent_handle add_torrent( - char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , fs::path const& save_path - , entry const& resume_data - , storage_mode_t storage_mode - , storage_constructor_type sc - , bool paused - , void* userdata); + torrent_handle add_torrent(add_torrent_params const&); void remove_torrent(torrent_handle const& h, int options); std::vector get_torrents(); - void set_severity_level(alert::severity_t s); + void check_torrent(boost::shared_ptr const& t); + void done_checking(boost::shared_ptr const& t); + + void set_alert_mask(int m); std::auto_ptr pop_alert(); alert const* wait_for_alert(time_duration max_wait); @@ -334,11 +268,29 @@ namespace libtorrent #ifndef TORRENT_DISABLE_DHT void set_dht_proxy(proxy_settings const& s) - { m_dht_proxy = s; } + { + m_dht_proxy = s; + m_dht_socket.set_proxy_settings(s); + } proxy_settings const& dht_proxy() const { return m_dht_proxy; } #endif +#ifndef TORRENT_DISABLE_GEO_IP + std::string as_name_for_ip(address const& a); + int as_for_ip(address const& a); + std::pair* lookup_as(int as); + bool load_asnum_db(char const* file); + bool has_asnum_db() const { return m_asnum_db; } + + bool load_country_db(char const* file); + bool has_country_db() const { return m_country_db; } + char const* country_for_ip(address const& a); +#endif + + void load_state(entry const& ses_state); + entry state() const; + #ifdef TORRENT_STATS void log_buffer_usage() { @@ -358,29 +310,36 @@ namespace libtorrent } #endif void start_lsd(); - void start_natpmp(); - void start_upnp(); + natpmp* start_natpmp(); + upnp* start_upnp(); void stop_lsd(); void stop_natpmp(); void stop_upnp(); + int next_port(); + // handles delayed alerts alert_manager m_alerts; std::pair allocate_buffer(int size); void free_buffer(char* buf, int size); + + char* allocate_disk_buffer(); void free_disk_buffer(char* buf); - - address m_external_address; + + void set_external_address(address const& ip); + address const& external_address() const { return m_external_address; } // private: void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih); +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR // this pool is used to allocate and recycle send // buffers from. boost::pool<> m_send_buffers; +#endif boost::mutex m_send_buffer_mutex; // the file pool that all storages in this session's @@ -391,20 +350,21 @@ namespace libtorrent // when they are destructed. file_pool m_files; + // this is where all active sockets are stored. + // the selector can sleep while there's no activity on + // them + io_service m_io_service; + // handles disk io requests asynchronously // peers have pointers into the disk buffer // pool, and must be destructed before this // object. The disk thread relies on the file // pool object, and must be destructed before - // m_files. + // m_files. The disk io thread posts completion + // events to the io service, and needs to be + // constructed after it. disk_io_thread m_disk_thread; - // this is where all active sockets are stored. - // the selector can sleep while there's no activity on - // them - io_service m_io_service; - asio::strand m_strand; - // this is a list of half-open tcp connections // (only outgoing connections) // this has to be one of the last @@ -422,6 +382,8 @@ namespace libtorrent tracker_manager m_tracker_manager; torrent_map m_torrents; + typedef std::list > check_queue_t; + check_queue_t m_queued_for_checking; // this maps sockets to their peer_connection // object. It is the complete list of all connected @@ -496,7 +458,17 @@ namespace libtorrent // should exit volatile bool m_abort; + // is true if the session is paused + bool m_paused; + + // the max number of unchoked peers as set by the user int m_max_uploads; + + // the number of unchoked peers as set by the auto-unchoker + // this should always be >= m_max_uploads + int m_allowed_upload_slots; + + // the max number of connections, as set by the user int m_max_connections; // the number of unchoked peers @@ -509,6 +481,10 @@ namespace libtorrent // recomputed. int m_unchoke_time_scaler; + // this is used to decide when to recalculate which + // torrents to keep queued and which to activate + int m_auto_manage_time_scaler; + // works like unchoke_time_scaler but it // is only decresed when the unchoke set // is recomputed, and when it reaches zero, @@ -521,6 +497,11 @@ namespace libtorrent // from the torrent with the most peers int m_disconnect_time_scaler; + // when this scaler reaches zero, it will + // scrape one of the auto managed, paused, + // torrents. + int m_auto_scrape_time_scaler; + // statistics gathered from all torrents. stat m_stat; @@ -530,9 +511,17 @@ namespace libtorrent // NAT or not. bool m_incoming_connection; - void second_tick(asio::error_code const& e); + void second_tick(error_code const& e); + void recalculate_auto_managed_torrents(); + void recalculate_unchoke_slots(int congested_torrents + , int uncongested_torrents); + ptime m_last_tick; + // when outgoing_ports is configured, this is the + // port we'll bind the next outgoing socket to + int m_next_port; + #ifndef TORRENT_DISABLE_DHT boost::intrusive_ptr m_dht; dht_settings m_dht_settings; @@ -545,6 +534,11 @@ namespace libtorrent // see m_external_listen_port. This is the same // but for the udp port used by the DHT. int m_external_udp_port; + + udp_socket m_dht_socket; + + void on_receive_udp(error_code const& e + , udp::endpoint const& ep, char const* buf, int len); #endif #ifndef TORRENT_DISABLE_ENCRYPTION @@ -555,6 +549,10 @@ namespace libtorrent boost::intrusive_ptr m_upnp; boost::intrusive_ptr m_lsd; + // 0 is natpmp 1 is upnp + int m_tcp_mapping[2]; + int m_udp_mapping[2]; + // the timer used to fire the second_tick deadline_timer m_timer; @@ -575,7 +573,7 @@ namespace libtorrent // the number of send buffers that are allocated int m_buffer_allocations; #endif -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING boost::shared_ptr create_log(std::string const& name , int instance, bool append = true); @@ -588,7 +586,9 @@ namespace libtorrent public: boost::shared_ptr m_logger; private: + #endif + address m_external_address; #ifndef TORRENT_DISABLE_EXTENSIONS typedef std::list m_as_peak; +#endif // the main working thread boost::scoped_ptr m_thread; - - // the thread that calls initialize_pieces() - // on all torrents before they start downloading - boost::scoped_ptr m_checker_thread; }; -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING struct tracker_logger : request_callback { tracker_logger(session_impl& ses): m_ses(ses) {} - void tracker_warning(std::string const& str) + void tracker_warning(tracker_request const& req + , std::string const& str) { debug_log("*** tracker warning: " + str); } @@ -622,7 +626,8 @@ namespace libtorrent , std::vector& peers , int interval , int complete - , int incomplete) + , int incomplete + , address const& external_ip) { std::stringstream s; s << "TRACKER RESPONSE:\n" @@ -636,6 +641,7 @@ namespace libtorrent if (!i->pid.is_all_zeros()) s << " " << i->pid; s << "\n"; } + s << "external ip: " << external_ip << "\n"; debug_log(s.str()); } diff --git a/libtorrent/include/libtorrent/bandwidth_manager.hpp b/libtorrent/include/libtorrent/bandwidth_manager.hpp index 9cf035e4b..ef58337c5 100644 --- a/libtorrent/include/libtorrent/bandwidth_manager.hpp +++ b/libtorrent/include/libtorrent/bandwidth_manager.hpp @@ -41,6 +41,10 @@ POSSIBILITY OF SUCH DAMAGE. #include #include +#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT +#include +#endif + #include "libtorrent/socket.hpp" #include "libtorrent/invariant_check.hpp" #include "libtorrent/assert.hpp" @@ -52,7 +56,6 @@ using boost::shared_ptr; using boost::intrusive_ptr; using boost::bind; -//#define TORRENT_VERBOSE_BANDWIDTH_LIMIT namespace libtorrent { @@ -73,6 +76,8 @@ struct history_entry history_entry(intrusive_ptr p, weak_ptr t , int a, ptime exp) : expires_at(exp), amount(a), peer(p), tor(t) {} + history_entry(int a, ptime exp) + : expires_at(exp), amount(a), peer(), tor() {} ptime expires_at; int amount; intrusive_ptr peer; @@ -80,7 +85,7 @@ struct history_entry }; template -T clamp(T val, T ceiling, T floor) throw() +T clamp(T val, T ceiling, T floor) { TORRENT_ASSERT(ceiling >= floor); if (val >= ceiling) return ceiling; @@ -88,27 +93,55 @@ T clamp(T val, T ceiling, T floor) throw() return val; } +template +struct assign_at_exit +{ + assign_at_exit(T& var, T val): var_(var), val_(val) {} + ~assign_at_exit() { var_ = val_; } + T& var_; + T val_; +}; + template struct bandwidth_manager { - bandwidth_manager(io_service& ios, int channel) throw() + bandwidth_manager(io_service& ios, int channel +#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT + , bool log = false +#endif + ) : m_ios(ios) , m_history_timer(m_ios) , m_limit(bandwidth_limit::inf) + , m_drain_quota(0) , m_current_quota(0) , m_channel(channel) , m_in_hand_out_bandwidth(false) , m_abort(false) - {} + { +#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT + if (log) + m_log.open("bandwidth_limiter.log", std::ios::trunc); + m_start = time_now(); +#endif + } - void throttle(int limit) throw() + void drain(int bytes) + { + mutex_t::scoped_lock l(m_mutex); + TORRENT_ASSERT(bytes >= 0); + m_drain_quota += bytes; + if (m_drain_quota > m_limit * 5) m_drain_quota = m_limit * 5; + } + + void throttle(int limit) { mutex_t::scoped_lock l(m_mutex); TORRENT_ASSERT(limit >= 0); m_limit = limit; } - int throttle() const throw() + int throttle() const { mutex_t::scoped_lock l(m_mutex); return m_limit; @@ -124,6 +157,22 @@ struct bandwidth_manager } #ifndef NDEBUG + bool is_queued(PeerConnection const* peer) const + { + mutex_t::scoped_lock l(m_mutex); + return is_queued(peer); + } + + bool is_queued(PeerConnection const* peer, boost::mutex::scoped_lock& l) const + { + for (typename queue_t::const_iterator i = m_queue.begin() + , end(m_queue.end()); i != end; ++i) + { + if (i->peer.get() == peer) return true; + } + return false; + } + bool is_in_history(PeerConnection const* peer) const { mutex_t::scoped_lock l(m_mutex); @@ -141,41 +190,35 @@ struct bandwidth_manager } #endif - int queue_size() const - { - mutex_t::scoped_lock l(m_mutex); - return m_queue.size(); - } - + int queue_size() const + { + mutex_t::scoped_lock l(m_mutex); + return m_queue.size(); + } + // non prioritized means that, if there's a line for bandwidth, // others will cut in front of the non-prioritized peers. // this is used by web seeds - void request_bandwidth(intrusive_ptr peer - , int blk, int priority) + void request_bandwidth(intrusive_ptr const& peer + , int blk, int priority) { mutex_t::scoped_lock l(m_mutex); INVARIANT_CHECK; if (m_abort) return; TORRENT_ASSERT(blk > 0); + TORRENT_ASSERT(!is_queued(peer.get(), l)); // make sure this peer isn't already in line // waiting for bandwidth -#ifndef NDEBUG - for (typename queue_t::iterator i = m_queue.begin() - , end(m_queue.end()); i != end; ++i) - { - TORRENT_ASSERT(i->peer < peer || peer < i->peer); - } -#endif - TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0); + TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0); - typename queue_t::reverse_iterator i(m_queue.rbegin()); - while (i != m_queue.rend() && priority > i->priority) - { - ++i->priority; - ++i; - } - m_queue.insert(i.base(), bw_queue_entry(peer, blk, priority)); + typename queue_t::reverse_iterator i(m_queue.rbegin()); + while (i != m_queue.rend() && priority > i->priority) + { + ++i->priority; + ++i; + } + m_queue.insert(i.base(), bw_queue_entry(peer, blk, priority)); if (!m_queue.empty()) hand_out_bandwidth(l); } @@ -205,25 +248,32 @@ private: void add_history_entry(history_entry const& e) { - try { INVARIANT_CHECK; + m_history.push_front(e); m_current_quota += e.amount; // in case the size > 1 there is already a timer // active that will be invoked, no need to set one up + +#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT + m_log << std::setw(7) << total_milliseconds(time_now() - m_start) << " + " + " queue: " << std::setw(3) << m_queue.size() + << " used: " << std::setw(7) << m_current_quota + << " limit: " << std::setw(7) << m_limit + << " history: " << std::setw(3) << m_history.size() + << std::endl; +#endif if (m_history.size() > 1) return; if (m_abort) return; - m_history_timer.expires_at(e.expires_at); + error_code ec; + m_history_timer.expires_at(e.expires_at, ec); m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1)); - } - catch (std::exception&) {} } - void on_history_expire(asio::error_code const& e) + void on_history_expire(error_code const& e) { - try { if (e) return; mutex_t::scoped_lock l(m_mutex); @@ -239,7 +289,17 @@ private: m_history.pop_back(); m_current_quota -= e.amount; TORRENT_ASSERT(m_current_quota >= 0); + +#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT + m_log << std::setw(7) << total_milliseconds(time_now() - m_start) << " - " + " queue: " << std::setw(3) << m_queue.size() + << " used: " << std::setw(7) << m_current_quota + << " limit: " << std::setw(7) << m_limit + << " history: " << std::setw(3) << m_history.size() + << std::endl; +#endif intrusive_ptr c = e.peer; + if (!c) continue; shared_ptr t = e.tor.lock(); l.unlock(); if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount); @@ -250,7 +310,8 @@ private: // now, wait for the next chunk to expire if (!m_history.empty() && !m_abort) { - m_history_timer.expires_at(m_history.back().expires_at); + error_code ec; + m_history_timer.expires_at(m_history.back().expires_at, ec); m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1)); } @@ -258,8 +319,6 @@ private: // means we can hand out more (in case there // are still consumers in line) if (!m_queue.empty()) hand_out_bandwidth(l); - } - catch (std::exception&) {} } void hand_out_bandwidth(boost::mutex::scoped_lock& l) @@ -268,8 +327,9 @@ private: // to the loop further down on the callstack if (m_in_hand_out_bandwidth) return; m_in_hand_out_bandwidth = true; + // set it to false when exiting function + assign_at_exit sg(m_in_hand_out_bandwidth, false); - try { INVARIANT_CHECK; ptime now(time_now()); @@ -279,17 +339,15 @@ private: // available bandwidth to hand out int amount = limit - m_current_quota; -#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT - std::cerr << " hand_out_bandwidht. m_queue.size() = " << m_queue.size() - << " amount = " << amount - << " limit = " << limit - << " m_current_quota = " << m_current_quota << std::endl; -#endif + if (amount <= 0) return; - if (amount <= 0) + if (m_drain_quota > 0) { - m_in_hand_out_bandwidth = false; - return; + int drain_amount = (std::min)(m_drain_quota, amount); + m_drain_quota -= drain_amount; + amount -= drain_amount; + add_history_entry(history_entry( + drain_amount, now + bw_window_size)); } queue_t tmp; @@ -356,9 +414,12 @@ private: } if (block_size > qe.max_block_size) block_size = qe.max_block_size; -#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT - std::cerr << " block_size = " << block_size << " amount = " << amount << std::endl; -#endif + if (amount < block_size / 4) + { + tmp.push_back(qe); +// m_queue.push_front(qe); + break; + } // so, hand out max_assignable, but no more than // the available bandwidth (amount) and no more @@ -375,14 +436,7 @@ private: add_history_entry(history_entry( qe.peer, t, hand_out_amount, now + bw_window_size)); } - if (!tmp.empty()) m_queue.insert(m_queue.begin(), tmp.begin(), tmp.end()); - } - catch (std::exception&) - { - m_in_hand_out_bandwidth = false; - throw; - } - m_in_hand_out_bandwidth = false; + if (!tmp.empty()) m_queue.insert(m_queue.begin(), tmp.begin(), tmp.end()); } @@ -400,6 +454,10 @@ private: // the rate limit (bytes per second) int m_limit; + // bytes to drain without handing out to a peer + // used to deduct the IP overhead + int m_drain_quota; + // the sum of all recently handed out bandwidth blocks int m_current_quota; @@ -421,6 +479,11 @@ private: bool m_in_hand_out_bandwidth; bool m_abort; + +#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT + std::ofstream m_log; + ptime m_start; +#endif }; } diff --git a/libtorrent/include/libtorrent/bencode.hpp b/libtorrent/include/libtorrent/bencode.hpp old mode 100755 new mode 100644 index 9bea1d846..9443e7a65 --- a/libtorrent/include/libtorrent/bencode.hpp +++ b/libtorrent/include/libtorrent/bencode.hpp @@ -103,28 +103,35 @@ namespace libtorrent namespace detail { template - void write_string(OutIt& out, const std::string& val) + int write_string(OutIt& out, const std::string& val) { - std::string::const_iterator end = val.begin() + val.length(); - std::copy(val.begin(), end, out); + int ret = val.length(); + std::string::const_iterator end = val.begin() + ret; + for (std::string::const_iterator i = val.begin() + , end(val.begin() + ret); i != end; ++i) + *out++ = *i; + return ret; } TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val); template - void write_integer(OutIt& out, entry::integer_type val) + int write_integer(OutIt& out, entry::integer_type val) { // the stack allocated buffer for keeping the // decimal representation of the number can // not hold number bigger than this: BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8); char buf[21]; + int ret = 0; for (char const* str = integer_to_str(buf, 21, val); *str != 0; ++str) { *out = *str; ++out; + ++ret; } + return ret; } template @@ -172,26 +179,31 @@ namespace libtorrent } } + // returns the number of bytes written template - void bencode_recursive(OutIt& out, const entry& e) + int bencode_recursive(OutIt& out, const entry& e) { + int ret = 0; switch(e.type()) { case entry::int_t: write_char(out, 'i'); - write_integer(out, e.integer()); + ret += write_integer(out, e.integer()); write_char(out, 'e'); + ret += 2; break; case entry::string_t: - write_integer(out, e.string().length()); + ret += write_integer(out, e.string().length()); write_char(out, ':'); - write_string(out, e.string()); + ret += write_string(out, e.string()); + ret += 1; break; case entry::list_t: write_char(out, 'l'); for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) - bencode_recursive(out, *i); + ret += bencode_recursive(out, *i); write_char(out, 'e'); + ret += 2; break; case entry::dictionary_t: write_char(out, 'd'); @@ -199,18 +211,21 @@ namespace libtorrent i != e.dict().end(); ++i) { // write key - write_integer(out, i->first.length()); + ret += write_integer(out, i->first.length()); write_char(out, ':'); - write_string(out, i->first); + ret += write_string(out, i->first); // write value - bencode_recursive(out, i->second); + ret += bencode_recursive(out, i->second); + ret += 1; } write_char(out, 'e'); + ret += 2; break; default: // do nothing break; } + return ret; } template @@ -225,6 +240,9 @@ namespace libtorrent if (in == end) { err = true; +#ifndef NDEBUG + ret.m_type_queried = false; +#endif return; } switch (*in) @@ -241,6 +259,9 @@ namespace libtorrent ++in; // 'e' ret = entry(entry::int_t); ret.integer() = boost::lexical_cast(val); +#ifndef NDEBUG + ret.m_type_queried = false; +#endif } break; // ---------------------------------------------- @@ -254,13 +275,25 @@ namespace libtorrent ret.list().push_back(entry()); entry& e = ret.list().back(); bdecode_recursive(in, end, e, err, depth + 1); - if (err) return; + if (err) + { +#ifndef NDEBUG + ret.m_type_queried = false; +#endif + return; + } if (in == end) { err = true; +#ifndef NDEBUG + ret.m_type_queried = false; +#endif return; } } +#ifndef NDEBUG + ret.m_type_queried = false; +#endif TORRENT_ASSERT(*in == 'e'); ++in; // 'e' } break; @@ -275,16 +308,34 @@ namespace libtorrent { entry key; bdecode_recursive(in, end, key, err, depth + 1); - if (err) return; + if (err || key.type() != entry::string_t) + { +#ifndef NDEBUG + ret.m_type_queried = false; +#endif + return; + } entry& e = ret[key.string()]; bdecode_recursive(in, end, e, err, depth + 1); - if (err) return; + if (err) + { +#ifndef NDEBUG + ret.m_type_queried = false; +#endif + return; + } if (in == end) { err = true; +#ifndef NDEBUG + ret.m_type_queried = false; +#endif return; } } +#ifndef NDEBUG + ret.m_type_queried = false; +#endif TORRENT_ASSERT(*in == 'e'); ++in; // 'e' } break; @@ -295,27 +346,45 @@ namespace libtorrent if (isdigit((unsigned char)*in)) { std::string len_s = read_until(in, end, ':', err); - if (err) return; + if (err) + { +#ifndef NDEBUG + ret.m_type_queried = false; +#endif + return; + } TORRENT_ASSERT(*in == ':'); ++in; // ':' int len = std::atoi(len_s.c_str()); ret = entry(entry::string_t); read_string(in, end, len, ret.string(), err); - if (err) return; + if (err) + { +#ifndef NDEBUG + ret.m_type_queried = false; +#endif + return; + } } else { err = true; +#ifndef NDEBUG + ret.m_type_queried = false; +#endif return; } +#ifndef NDEBUG + ret.m_type_queried = false; +#endif } } } template - void bencode(OutIt out, const entry& e) + int bencode(OutIt out, const entry& e) { - detail::bencode_recursive(out, e); + return detail::bencode_recursive(out, e); } template @@ -324,18 +393,23 @@ namespace libtorrent entry e; bool err = false; detail::bdecode_recursive(start, end, e, err, 0); - if (err) - { -#ifdef BOOST_NO_EXCEPTIONS - return entry(); -#else - throw invalid_encoding(); -#endif - } + TORRENT_ASSERT(e.m_type_queried == false); + if (err) return entry(); return e; } + template + entry bdecode(InIt start, InIt end, int& len) + { + entry e; + bool err = false; + InIt s = start; + detail::bdecode_recursive(start, end, e, err, 0); + len = std::distance(s, start); + TORRENT_ASSERT(len >= 0); + if (err) return entry(); + return e; + } } #endif // TORRENT_BENCODE_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/bitfield.hpp b/libtorrent/include/libtorrent/bitfield.hpp new file mode 100644 index 000000000..fe14cfe1c --- /dev/null +++ b/libtorrent/include/libtorrent/bitfield.hpp @@ -0,0 +1,241 @@ +/* + +Copyright (c) 2008, Arvid Norberg +All rights reserved. + +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. + +*/ + +#ifndef TORRENT_BITFIELD_HPP_INCLUDED +#define TORRENT_BITFIELD_HPP_INCLUDED + +#include "libtorrent/assert.hpp" +#include "libtorrent/config.hpp" + +namespace libtorrent +{ + struct TORRENT_EXPORT bitfield + { + bitfield(): m_bytes(0), m_size(0), m_own(false) {} + bitfield(int bits): m_bytes(0), m_size(0) + { resize(bits); } + bitfield(int bits, bool val): m_bytes(0), m_size(0) + { resize(bits, val); } + bitfield(char const* bytes, int bits): m_bytes(0), m_size(0) + { assign(bytes, bits); } + bitfield(bitfield const& rhs): m_bytes(0), m_size(0), m_own(false) + { assign(rhs.bytes(), rhs.size()); } + + void borrow_bytes(char* bytes, int bits) + { + dealloc(); + m_bytes = (unsigned char*)bytes; + m_size = bits; + m_own = false; + } + ~bitfield() { dealloc(); } + + void assign(char const* bytes, int bits) + { resize(bits); memcpy(m_bytes, bytes, (bits + 7) / 8); } + + bool operator[](int index) const + { return get_bit(index); } + + bool get_bit(int index) const + { + TORRENT_ASSERT(index >= 0); + TORRENT_ASSERT(index < m_size); + return m_bytes[index / 8] & (0x80 >> (index & 7)); + } + + void clear_bit(int index) + { + TORRENT_ASSERT(index >= 0); + TORRENT_ASSERT(index < m_size); + m_bytes[index / 8] &= ~(0x80 >> (index & 7)); + } + + void set_bit(int index) + { + TORRENT_ASSERT(index >= 0); + TORRENT_ASSERT(index < m_size); + m_bytes[index / 8] |= (0x80 >> (index & 7)); + } + + std::size_t size() const { return m_size; } + bool empty() const { return m_size == 0; } + + char const* bytes() const { return (char*)m_bytes; } + + bitfield& operator=(bitfield const& rhs) + { + assign(rhs.bytes(), rhs.size()); + return *this; + } + + int count() const + { + // 0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111, + // 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111 + const static char num_bits[] = + { + 0, 1, 1, 2, 1, 2, 2, 3, + 1, 2, 2, 3, 2, 3, 3, 4 + }; + + int ret = 0; + const int num_bytes = m_size / 8; + for (int i = 0; i < num_bytes; ++i) + { + ret += num_bits[m_bytes[i] & 0xf] + num_bits[m_bytes[i] >> 4]; + } + + int rest = m_size - num_bytes * 8; + for (int i = 0; i < rest; ++i) + { + ret += (m_bytes[num_bytes] >> (7-i)) & 1; + } + TORRENT_ASSERT(ret <= m_size); + TORRENT_ASSERT(ret >= 0); + return ret; + } + + struct const_iterator + { + friend struct bitfield; + + typedef bool value_type; + typedef ptrdiff_t difference_type; + typedef bool const* pointer; + typedef bool& reference; + typedef std::forward_iterator_tag iterator_category; + + bool operator*() { return *byte & bit; } + const_iterator& operator++() { inc(); return *this; } + const_iterator operator++(int) + { const_iterator ret(*this); inc(); return ret; } + const_iterator& operator--() { dec(); return *this; } + const_iterator operator--(int) + { const_iterator ret(*this); dec(); return ret; } + + const_iterator(): byte(0), bit(0x80) {} + bool operator==(const_iterator const& rhs) const + { return byte == rhs.byte && bit == rhs.bit; } + + bool operator!=(const_iterator const& rhs) const + { return byte != rhs.byte || bit != rhs.bit; } + + private: + void inc() + { + TORRENT_ASSERT(byte); + if (bit == 0x01) + { + bit = 0x80; + ++byte; + } + else + { + bit >>= 1; + } + } + void dec() + { + TORRENT_ASSERT(byte); + if (bit == 0x80) + { + bit = 0x01; + --byte; + } + else + { + bit <<= 1; + } + } + const_iterator(unsigned char const* ptr, int offset) + : byte(ptr), bit(0x80 >> offset) {} + unsigned char const* byte; + int bit; + }; + + const_iterator begin() const { return const_iterator(m_bytes, 0); } + const_iterator end() const { return const_iterator(m_bytes + m_size / 8, m_size & 7); } + + void resize(int bits, bool val) + { + resize(bits); + if (val) set_all(); else clear_all(); + } + + void set_all() + { + memset(m_bytes, 0xff, (m_size + 7) / 8); + } + + void clear_all() + { + memset(m_bytes, 0x00, (m_size + 7) / 8); + } + + void resize(int bits) + { + const int bytes = (bits + 7) / 8; + if (m_bytes) + { + if (m_own) + { + m_bytes = (unsigned char*)realloc(m_bytes, bytes); + m_own = true; + } + else if (bits > m_size) + { + unsigned char* tmp = (unsigned char*)malloc(bytes); + memcpy(tmp, m_bytes, (std::min)((m_size + 7)/ 8, bytes)); + m_bytes = tmp; + m_own = true; + } + } + else + { + m_bytes = (unsigned char*)malloc(bytes); + m_own = true; + } + m_size = bits; + } + + private: + + void dealloc() { if (m_own) free(m_bytes); m_bytes = 0; } + unsigned char* m_bytes; + int m_size; // in bits + bool m_own; + }; + +} + +#endif // TORRENT_BITFIELD_HPP_INCLUDED + diff --git a/libtorrent/include/libtorrent/broadcast_socket.hpp b/libtorrent/include/libtorrent/broadcast_socket.hpp index f7aae342b..3a8d6a76e 100644 --- a/libtorrent/include/libtorrent/broadcast_socket.hpp +++ b/libtorrent/include/libtorrent/broadcast_socket.hpp @@ -51,7 +51,7 @@ namespace libtorrent int common_bits(unsigned char const* b1 , unsigned char const* b2, int n); - TORRENT_EXPORT address guess_local_address(asio::io_service&); + TORRENT_EXPORT address guess_local_address(io_service&); typedef boost::function receive_handler_t; @@ -59,11 +59,11 @@ namespace libtorrent class TORRENT_EXPORT broadcast_socket { public: - broadcast_socket(asio::io_service& ios, udp::endpoint const& multicast_endpoint + broadcast_socket(io_service& ios, udp::endpoint const& multicast_endpoint , receive_handler_t const& handler, bool loopback = true); ~broadcast_socket() { close(); } - void send(char const* buffer, int size, asio::error_code& ec); + void send(char const* buffer, int size, error_code& ec); void close(); private: @@ -74,12 +74,29 @@ namespace libtorrent boost::shared_ptr socket; char buffer[1024]; udp::endpoint remote; + void close() + { + if (!socket) return; + error_code ec; + socket->close(ec); + } }; - void on_receive(socket_entry* s, asio::error_code const& ec + void on_receive(socket_entry* s, error_code const& ec , std::size_t bytes_transferred); + void open_unicast_socket(io_service& ios, address const& addr); + void open_multicast_socket(io_service& ios, address const& addr + , bool loopback); + // these sockets are used to + // join the multicast group (on each interface) + // and receive multicast messages std::list m_sockets; + // these sockets are not bound to any + // specific port and are used to + // send messages to the multicast group + // and receive unicast responses + std::list m_unicast_sockets; udp::endpoint m_multicast_endpoint; receive_handler_t m_on_receive; diff --git a/libtorrent/include/libtorrent/bt_peer_connection.hpp b/libtorrent/include/libtorrent/bt_peer_connection.hpp old mode 100755 new mode 100644 index d07dcb2dd..a900bfc7e --- a/libtorrent/include/libtorrent/bt_peer_connection.hpp +++ b/libtorrent/include/libtorrent/bt_peer_connection.hpp @@ -103,6 +103,8 @@ namespace libtorrent , tcp::endpoint const& remote , policy::peer* peerinfo); + void start(); + ~bt_peer_connection(); #ifndef TORRENT_DISABLE_ENCRYPTION @@ -140,9 +142,9 @@ namespace libtorrent // called from the main loop when this connection has any // work to do. - void on_sent(asio::error_code const& error + void on_sent(error_code const& error , std::size_t bytes_transferred); - void on_receive(asio::error_code const& error + void on_receive(error_code const& error , std::size_t bytes_transferred); virtual void get_specific_peer_info(peer_info& p) const; @@ -207,9 +209,9 @@ namespace libtorrent void write_not_interested(); void write_request(peer_request const& r); void write_cancel(peer_request const& r); - void write_bitfield(std::vector const& bitfield); + void write_bitfield(); void write_have(int index); - void write_piece(peer_request const& r, char* buffer); + void write_piece(peer_request const& r, disk_buffer_holder& buffer); void write_handshake(); #ifndef TORRENT_DISABLE_EXTENSIONS void write_extensions(); @@ -268,10 +270,12 @@ namespace libtorrent // initializes m_RC4_handler void init_pe_RC4_handler(char const* secret, sha1_hash const& stream_key); +public: + // these functions encrypt the send buffer if m_rc4_encrypted // is true, otherwise it passes the call to the // peer_connection functions of the same names - void send_buffer(char* buf, int size); + void send_buffer(char* buf, int size, int flags = 0); buffer::interval allocate_send_buffer(int size); template void append_send_buffer(char* buffer, int size, Destructor const& destructor) @@ -284,6 +288,8 @@ namespace libtorrent } void setup_send(); +private: + // Returns offset at which bytestream (src, src + src_size) // matches bytestream(target, target + target_size). // If no sync found, return -1 @@ -358,6 +364,7 @@ namespace libtorrent // the peer indicated that it supports the // extension protocol bool m_supports_extensions; + char m_reserved_bits[20]; #endif bool m_supports_dht_port; bool m_supports_fast; @@ -382,7 +389,7 @@ namespace libtorrent // initialized during write_pe1_2_dhkey, and destroyed on // creation of m_RC4_handler. Cannot reinitialize once // initialized. - boost::scoped_ptr m_DH_key_exchange; + boost::scoped_ptr m_dh_key_exchange; // if RC4 is negotiated, this is used for // encryption/decryption during the entire session. Destroyed diff --git a/libtorrent/include/libtorrent/buffer.hpp b/libtorrent/include/libtorrent/buffer.hpp index a823a7677..425a6a634 100644 --- a/libtorrent/include/libtorrent/buffer.hpp +++ b/libtorrent/include/libtorrent/buffer.hpp @@ -44,6 +44,11 @@ class buffer public: struct interval { + interval() + : begin(0) + , end(0) + {} + interval(char* begin, char* end) : begin(begin) , end(end) diff --git a/libtorrent/include/libtorrent/chained_buffer.hpp b/libtorrent/include/libtorrent/chained_buffer.hpp index 82fcb65c5..caf2e89be 100644 --- a/libtorrent/include/libtorrent/chained_buffer.hpp +++ b/libtorrent/include/libtorrent/chained_buffer.hpp @@ -34,12 +34,20 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_CHAINED_BUFFER_HPP_INCLUDED #include +#include +#if BOOST_VERSION < 103500 #include +#else +#include +#endif #include #include namespace libtorrent { +#if BOOST_VERSION >= 103500 + namespace asio = boost::asio; +#endif struct chained_buffer { chained_buffer(): m_bytes(0), m_capacity(0) {} diff --git a/libtorrent/include/libtorrent/config.hpp b/libtorrent/include/libtorrent/config.hpp old mode 100755 new mode 100644 diff --git a/libtorrent/include/libtorrent/connection_queue.hpp b/libtorrent/include/libtorrent/connection_queue.hpp index c229ec217..527b862df 100644 --- a/libtorrent/include/libtorrent/connection_queue.hpp +++ b/libtorrent/include/libtorrent/connection_queue.hpp @@ -40,6 +40,10 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket.hpp" #include "libtorrent/time.hpp" +#ifdef TORRENT_CONNECTION_LOGGING +#include +#endif + namespace libtorrent { @@ -48,30 +52,30 @@ class connection_queue : public boost::noncopyable public: connection_queue(io_service& ios); - bool free_slots() const; + // if there are no free slots, returns the negative + // number of queued up connections + int free_slots() const; void enqueue(boost::function const& on_connect , boost::function const& on_timeout - , time_duration timeout); + , time_duration timeout, int priority = 0); void done(int ticket); void limit(int limit); int limit() const; void close(); #ifndef NDEBUG - void check_invariant() const; - #endif private: void try_connect(); - void on_timeout(asio::error_code const& e); + void on_timeout(error_code const& e); struct entry { - entry(): connecting(false), ticket(0), expires(max_time()) {} + entry(): connecting(false), ticket(0), expires(max_time()), priority(0) {} // called when the connection is initiated boost::function on_connect; // called if done hasn't been called within the timeout @@ -80,6 +84,7 @@ private: int ticket; ptime expires; time_duration timeout; + int priority; }; std::list m_queue; @@ -97,6 +102,9 @@ private: #ifndef NDEBUG bool m_in_timeout_function; #endif +#ifdef TORRENT_CONNECTION_LOGGING + std::ofstream m_log; +#endif }; } diff --git a/libtorrent/include/libtorrent/create_torrent.hpp b/libtorrent/include/libtorrent/create_torrent.hpp new file mode 100644 index 000000000..32c7a41f2 --- /dev/null +++ b/libtorrent/include/libtorrent/create_torrent.hpp @@ -0,0 +1,200 @@ +/* + +Copyright (c) 2008, Arvid Norberg +All rights reserved. + +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. + +*/ + +#ifndef TORRENT_CREATE_TORRENT_HPP_INCLUDED +#define TORRENT_CREATE_TORRENT_HPP_INCLUDED + +#include "libtorrent/bencode.hpp" +#include "libtorrent/peer_id.hpp" +#include "libtorrent/file_storage.hpp" +#include "libtorrent/file_pool.hpp" +#include "libtorrent/config.hpp" +#include "libtorrent/storage.hpp" +#include "libtorrent/hasher.hpp" + +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(push, 1) +#endif + +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +namespace libtorrent +{ + namespace fs = boost::filesystem; + namespace pt = boost::posix_time; + + struct TORRENT_EXPORT create_torrent + { + create_torrent(file_storage& fs, int piece_size); + create_torrent(file_storage& fs); + entry generate() const; + + file_storage const& files() const { return m_files; } + + void set_comment(char const* str); + void set_creator(char const* str); + void set_hash(int index, sha1_hash const& h); + void add_url_seed(std::string const& url); + void add_node(std::pair const& node); + void add_tracker(std::string const& url, int tier = 0); + + int num_pieces() const { return m_files.num_pieces(); } + int piece_length() const { return m_files.piece_length(); } + int piece_size(int i) const { return m_files.piece_size(i); } + + private: + + file_storage& m_files; + + // the urls to the trackers + typedef std::pair announce_entry; + std::vector m_urls; + + std::vector m_url_seeds; + + std::vector m_piece_hash; + + // dht nodes to add to the routing table/bootstrap from + typedef std::vector > nodes_t; + nodes_t m_nodes; + + // the hash that identifies this torrent + // is mutable because it's calculated + // lazily + mutable sha1_hash m_info_hash; + + // if a creation date is found in the torrent file + // this will be set to that, otherwise it'll be + // 1970, Jan 1 + pt::ptime m_creation_date; + + // if a comment is found in the torrent file + // this will be set to that comment + std::string m_comment; + + // an optional string naming the software used + // to create the torrent file + std::string m_created_by; + + // this is used when creating a torrent. If there's + // only one file there are cases where it's impossible + // to know if it should be written as a multifile torrent + // or not. e.g. test/test there's one file and one directory + // and they have the same name. + bool m_multifile; + + // this is true if the torrent is private. i.e., is should not + // be announced on the dht + bool m_private; + }; + + namespace detail + { + inline bool default_pred(boost::filesystem::path const&) { return true; } + + inline void nop(int i) {} + + template + void add_files_impl(file_storage& fs, boost::filesystem::path const& p + , boost::filesystem::path const& l, Pred pred) + { + using boost::filesystem::path; + using boost::filesystem::directory_iterator; + std::string const& leaf = l.leaf(); + if (leaf == ".." || leaf == ".") return; + if (!pred(l)) return; + path f(p / l); + if (is_directory(f)) + { + for (directory_iterator i(f), end; i != end; ++i) + add_files_impl(fs, p, l / i->leaf(), pred); + } + else + { + fs.add_file(l, file_size(f)); + } + } + } + + template + void add_files(file_storage& fs, boost::filesystem::path const& file, Pred p) + { + detail::add_files_impl(fs, complete(file).branch_path(), file.leaf(), p); + } + + inline void add_files(file_storage& fs, boost::filesystem::path const& file) + { + detail::add_files_impl(fs, complete(file).branch_path(), file.leaf(), detail::default_pred); + } + + template + void set_piece_hashes(create_torrent& t, boost::filesystem::path const& p, Fun f) + { + file_pool fp; + boost::scoped_ptr st( + default_storage_constructor(const_cast(t.files()), p, fp)); + + // calculate the hash for all pieces + int num = t.num_pieces(); + std::vector buf(t.piece_length()); + for (int i = 0; i < num; ++i) + { + // read hits the disk and will block. Progress should + // be updated in between reads + st->read(&buf[0], i, 0, t.piece_size(i)); + hasher h(&buf[0], t.piece_size(i)); + t.set_hash(i, h.final()); + f(i); + } + } + + inline void set_piece_hashes(create_torrent& t, boost::filesystem::path const& p) + { + set_piece_hashes(t, p, detail::nop); + } + +} + +#endif + diff --git a/libtorrent/include/libtorrent/debug.hpp b/libtorrent/include/libtorrent/debug.hpp old mode 100755 new mode 100644 index 96c2c9dc7..0f2dad20b --- a/libtorrent/include/libtorrent/debug.hpp +++ b/libtorrent/include/libtorrent/debug.hpp @@ -60,17 +60,21 @@ namespace libtorrent { logger(fs::path const& logpath, fs::path const& filename, int instance, bool append = true) { +#ifndef BOOST_NO_EXCEPTIONS try { +#endif fs::path dir(fs::complete(logpath / ("libtorrent_logs" + boost::lexical_cast(instance)))); if (!fs::exists(dir)) fs::create_directories(dir); m_file.open((dir / filename).string().c_str(), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::out)); *this << "\n\n\n*** starting log ***\n"; +#ifndef BOOST_NO_EXCEPTIONS } catch (std::exception& e) { std::cerr << "failed to create log '" << filename.string() << "': " << e.what() << std::endl; } +#endif } template diff --git a/libtorrent/include/libtorrent/disk_buffer_holder.hpp b/libtorrent/include/libtorrent/disk_buffer_holder.hpp new file mode 100644 index 000000000..31be6b3c7 --- /dev/null +++ b/libtorrent/include/libtorrent/disk_buffer_holder.hpp @@ -0,0 +1,65 @@ +/* + +Copyright (c) 2008, Arvid Norberg +All rights reserved. + +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. + +*/ + +#ifndef TORRENT_DISK_BUFFER_HOLDER_HPP_INCLUDED +#define TORRENT_DISK_BUFFER_HOLDER_HPP_INCLUDED + +#include "libtorrent/config.hpp" + +namespace libtorrent +{ + + namespace aux { class session_impl; } + class disk_io_thread; + + struct TORRENT_EXPORT disk_buffer_holder + { + disk_buffer_holder(aux::session_impl& ses, char* buf); + disk_buffer_holder(disk_io_thread& iothread, char* buf); + ~disk_buffer_holder(); + char* release(); + char* get() const { return m_buf; } + void reset(char* buf = 0); + + typedef char* (disk_buffer_holder::*unspecified_bool_type)(); + operator unspecified_bool_type() const + { return m_buf == 0? 0: &disk_buffer_holder::release; } + + private: + disk_io_thread& m_iothread; + char* m_buf; + }; + +} + +#endif + diff --git a/libtorrent/include/libtorrent/disk_io_thread.hpp b/libtorrent/include/libtorrent/disk_io_thread.hpp index 4e0e95adf..3556c3cf6 100644 --- a/libtorrent/include/libtorrent/disk_io_thread.hpp +++ b/libtorrent/include/libtorrent/disk_io_thread.hpp @@ -42,14 +42,24 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include #include +#include #include #include "libtorrent/config.hpp" +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR +#include +#endif namespace libtorrent { + struct cached_piece_info + { + int piece; + std::vector blocks; + ptime last_use; + }; + struct disk_io_job { disk_io_job() @@ -69,6 +79,11 @@ namespace libtorrent , move_storage , release_files , delete_files + , check_fastresume + , check_files + , save_resume_data + , rename_file + , abort_thread }; action_t action; @@ -78,25 +93,65 @@ namespace libtorrent boost::intrusive_ptr storage; // arguments used for read and write int piece, offset; - // used for move_storage. On errors, this is set + // used for move_storage and rename_file. On errors, this is set // to the error message std::string str; + // on error, this is set to the path of the + // file the disk operation failed on + std::string error_file; + // priority decides whether or not this // job will skip entries in the queue or // not. It always skips in front of entries // with lower priority int priority; + boost::shared_ptr resume_data; + // this is called when operation completes boost::function callback; }; + struct cache_status + { + cache_status() + : blocks_written(0) + , writes(0) + , blocks_read(0) + , blocks_read_hit(0) + , reads(0) + , cache_size(0) + , read_cache_size(0) + {} + + // the number of 16kB blocks written + size_type blocks_written; + // the number of write operations used + size_type writes; + // (blocks_written - writes) / blocks_written represents the + // "cache hit" ratio in the write cache + // the number of blocks read + + // the number of blocks passed back to the bittorrent engine + size_type blocks_read; + // the number of blocks that was just copied from the read cache + size_type blocks_read_hit; + // the number of read operations used + size_type reads; + + // the number of blocks in the cache (both read and write) + int cache_size; + + // the number of blocks in the cache used for read cache + int read_cache_size; + }; + // this is a singleton consisting of the thread and a queue // of disk io jobs struct disk_io_thread : boost::noncopyable { - disk_io_thread(int block_size = 16 * 1024); + disk_io_thread(io_service& ios, int block_size = 16 * 1024); ~disk_io_thread(); #ifdef TORRENT_STATS @@ -112,10 +167,6 @@ namespace libtorrent , boost::function const& f = boost::function()); -#ifndef NDEBUG - disk_io_job find_job(boost::intrusive_ptr s - , int action, int piece) const; -#endif // keep track of the number of bytes in the job queue // at any given time. i.e. the sum of all buffer_size. // this is used to slow down the download global download @@ -123,28 +174,119 @@ namespace libtorrent size_type queue_buffer_size() const { return m_queue_buffer_size; } + void get_cache_info(sha1_hash const& ih + , std::vector& ret) const; + + cache_status status() const; + void set_cache_size(int s); + void set_cache_expiry(int ex); + void operator()(); +#ifndef NDEBUG + bool is_disk_buffer(char* buffer) const; +#endif + char* allocate_buffer(); void free_buffer(char* buf); +#ifndef NDEBUG + void check_invariant() const; +#endif + private: + struct cached_piece_entry + { + int piece; + // storage this piece belongs to + boost::intrusive_ptr storage; + // the last time a block was writting to this piece + ptime last_use; + // the number of blocks in the cache for this piece + int num_blocks; + // the pointers to the block data + boost::shared_array blocks; + }; + typedef boost::recursive_mutex mutex_t; - mutable mutex_t m_mutex; + typedef std::list cache_t; + + // cache operations + cache_t::iterator find_cached_piece( + cache_t& cache, disk_io_job const& j + , mutex_t::scoped_lock& l); + + // write cache operations + void flush_oldest_piece(mutex_t::scoped_lock& l); + void flush_expired_pieces(); + void flush_and_remove(cache_t::iterator i, mutex_t::scoped_lock& l); + void flush(cache_t::iterator i, mutex_t::scoped_lock& l); + void cache_block(disk_io_job& j, mutex_t::scoped_lock& l); + + // read cache operations + bool clear_oldest_read_piece(cache_t::iterator ignore + , mutex_t::scoped_lock& l); + int read_into_piece(cached_piece_entry& p, int start_block, mutex_t::scoped_lock& l); + int cache_read_block(disk_io_job const& j, mutex_t::scoped_lock& l); + void free_piece(cached_piece_entry& p, mutex_t::scoped_lock& l); + bool make_room(int num_blocks + , cache_t::iterator ignore + , mutex_t::scoped_lock& l); + int try_read_from_cache(disk_io_job const& j); + + // this mutex only protects m_jobs, m_queue_buffer_size + // and m_abort + mutable mutex_t m_queue_mutex; boost::condition m_signal; bool m_abort; std::list m_jobs; size_type m_queue_buffer_size; - // memory pool for read and write operations - boost::pool<> m_pool; + // this protects the piece cache and related members + mutable mutex_t m_piece_mutex; + // write cache + cache_t m_pieces; + + // read cache + cache_t m_read_pieces; -#ifndef NDEBUG - int m_block_size; - disk_io_job m_current; + // total number of blocks in use by both the read + // and the write cache. This is not supposed to + // exceed m_cache_size + cache_status m_cache_stats; + int m_num_cached_blocks; + + // in (16kB) blocks + int m_cache_size; + + // expiration time of cache entries in seconds + int m_cache_expiry; + + // if set to true, each piece flush will allocate + // one piece worth of temporary memory on the heap + // and copy the block data into it, and then perform + // a single write operation from that buffer. + // if memory is constrained, that temporary buffer + // might is avoided by setting this to false. + // in case the allocation fails, the piece flush + // falls back to writing each block separately. + bool m_coalesce_writes; + bool m_coalesce_reads; + bool m_use_read_cache; + + // this only protects the pool allocator + mutable mutex_t m_pool_mutex; +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR + // memory pool for read and write operations + // and disk cache + boost::pool<> m_pool; #endif + // number of bytes per block. The BitTorrent + // protocol defines the block size to 16 KiB. + int m_block_size; + #ifdef TORRENT_DISK_STATS std::ofstream m_log; #endif @@ -152,6 +294,11 @@ namespace libtorrent int m_allocations; #endif + size_type m_writes; + size_type m_blocks_written; + + io_service& m_ios; + // thread for performing blocking disk io operations boost::thread m_disk_io_thread; }; diff --git a/libtorrent/include/libtorrent/entry.hpp b/libtorrent/include/libtorrent/entry.hpp old mode 100755 new mode 100644 index eb4aafe34..473eb1ca8 --- a/libtorrent/include/libtorrent/entry.hpp +++ b/libtorrent/include/libtorrent/entry.hpp @@ -206,6 +206,16 @@ namespace libtorrent }; #endif +#ifndef NDEBUG + public: + // in debug mode this is set to false by bdecode + // to indicate that the program has not yet queried + // the type of this entry, and sould not assume + // that it has a certain type. This is asserted in + // the accessor functions. This does not apply if + // exceptions are used. + mutable bool m_type_queried; +#endif }; inline std::ostream& operator<<(std::ostream& os, const entry& e) @@ -214,11 +224,14 @@ namespace libtorrent return os; } - inline entry::data_type entry::type() const { return m_type; } + inline entry::data_type entry::type() const + { +#ifndef NDEBUG + m_type_queried = true; +#endif + return m_type; + } - inline entry::entry(): m_type(undefined_t) {} - inline entry::entry(data_type t): m_type(t) { construct(t); } - inline entry::entry(const entry& e) { copy(e); } inline entry::~entry() { destruct(); } inline void entry::operator=(const entry& e) @@ -227,12 +240,13 @@ namespace libtorrent copy(e); } - inline entry::integer_type& entry::integer() { if (m_type == undefined_t) construct(int_t); #ifndef BOOST_NO_EXCEPTIONS if (m_type != int_t) throw type_error("invalid type requested from entry"); +#elif !defined NDEBUG + TORRENT_ASSERT(m_type_queried); #endif TORRENT_ASSERT(m_type == int_t); return *reinterpret_cast(data); @@ -242,6 +256,8 @@ namespace libtorrent { #ifndef BOOST_NO_EXCEPTIONS if (m_type != int_t) throw type_error("invalid type requested from entry"); +#elif !defined NDEBUG + TORRENT_ASSERT(m_type_queried); #endif TORRENT_ASSERT(m_type == int_t); return *reinterpret_cast(data); @@ -252,6 +268,8 @@ namespace libtorrent if (m_type == undefined_t) construct(string_t); #ifndef BOOST_NO_EXCEPTIONS if (m_type != string_t) throw type_error("invalid type requested from entry"); +#elif !defined NDEBUG + TORRENT_ASSERT(m_type_queried); #endif TORRENT_ASSERT(m_type == string_t); return *reinterpret_cast(data); @@ -261,6 +279,8 @@ namespace libtorrent { #ifndef BOOST_NO_EXCEPTIONS if (m_type != string_t) throw type_error("invalid type requested from entry"); +#elif !defined NDEBUG + TORRENT_ASSERT(m_type_queried); #endif TORRENT_ASSERT(m_type == string_t); return *reinterpret_cast(data); @@ -271,6 +291,8 @@ namespace libtorrent if (m_type == undefined_t) construct(list_t); #ifndef BOOST_NO_EXCEPTIONS if (m_type != list_t) throw type_error("invalid type requested from entry"); +#elif !defined NDEBUG + TORRENT_ASSERT(m_type_queried); #endif TORRENT_ASSERT(m_type == list_t); return *reinterpret_cast(data); @@ -280,6 +302,8 @@ namespace libtorrent { #ifndef BOOST_NO_EXCEPTIONS if (m_type != list_t) throw type_error("invalid type requested from entry"); +#elif !defined NDEBUG + TORRENT_ASSERT(m_type_queried); #endif TORRENT_ASSERT(m_type == list_t); return *reinterpret_cast(data); @@ -290,6 +314,8 @@ namespace libtorrent if (m_type == undefined_t) construct(dictionary_t); #ifndef BOOST_NO_EXCEPTIONS if (m_type != dictionary_t) throw type_error("invalid type requested from entry"); +#elif !defined NDEBUG + TORRENT_ASSERT(m_type_queried); #endif TORRENT_ASSERT(m_type == dictionary_t); return *reinterpret_cast(data); @@ -299,6 +325,8 @@ namespace libtorrent { #ifndef BOOST_NO_EXCEPTIONS if (m_type != dictionary_t) throw type_error("invalid type requested from entry"); +#elif !defined NDEBUG + TORRENT_ASSERT(m_type_queried); #endif TORRENT_ASSERT(m_type == dictionary_t); return *reinterpret_cast(data); diff --git a/libtorrent/include/libtorrent/enum_net.hpp b/libtorrent/include/libtorrent/enum_net.hpp index 56d89d472..643c4c0c0 100644 --- a/libtorrent/include/libtorrent/enum_net.hpp +++ b/libtorrent/include/libtorrent/enum_net.hpp @@ -43,12 +43,23 @@ namespace libtorrent { address interface_address; address netmask; + char name[64]; + }; + + struct ip_route + { + address destination; + address netmask; + address gateway; + char name[64]; }; // returns a list of the configured IP interfaces // on the machine - TORRENT_EXPORT std::vector enum_net_interfaces(asio::io_service& ios - , asio::error_code& ec); + TORRENT_EXPORT std::vector enum_net_interfaces(io_service& ios + , error_code& ec); + + TORRENT_EXPORT std::vector enum_routes(io_service& ios, error_code& ec); // returns true if the specified address is on the same // local network as the specified interface @@ -56,9 +67,11 @@ namespace libtorrent // returns true if the specified address is on the same // local network as us - TORRENT_EXPORT bool in_local_network(asio::io_service& ios, address const& addr, asio::error_code& ec); + TORRENT_EXPORT bool in_local_network(io_service& ios, address const& addr + , error_code& ec); - TORRENT_EXPORT address router_for_interface(address const interface, asio::error_code& ec); + TORRENT_EXPORT address get_default_gateway(io_service& ios + , error_code& ec); } #endif diff --git a/libtorrent/include/libtorrent/escape_string.hpp b/libtorrent/include/libtorrent/escape_string.hpp old mode 100755 new mode 100644 index e0e743e1e..660dd4d08 --- a/libtorrent/include/libtorrent/escape_string.hpp +++ b/libtorrent/include/libtorrent/escape_string.hpp @@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_ESCAPE_STRING_HPP_INCLUDED #include +#include #include "libtorrent/config.hpp" namespace libtorrent @@ -41,6 +42,17 @@ namespace libtorrent std::string TORRENT_EXPORT unescape_string(std::string const& s); std::string TORRENT_EXPORT escape_string(const char* str, int len); std::string TORRENT_EXPORT escape_path(const char* str, int len); + + // encodes a string using the base64 scheme + TORRENT_EXPORT std::string base64encode(std::string const& s); + // encodes a string using the base32 scheme + TORRENT_EXPORT std::string base32encode(std::string const& s); + TORRENT_EXPORT std::string base32decode(std::string const& s); + + TORRENT_EXPORT boost::optional url_has_argument( + std::string const& url, std::string argument); + + TORRENT_EXPORT std::string to_hex(std::string const& s); } #endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/extensions.hpp b/libtorrent/include/libtorrent/extensions.hpp index fd48588e1..b06a0fc74 100644 --- a/libtorrent/include/libtorrent/extensions.hpp +++ b/libtorrent/include/libtorrent/extensions.hpp @@ -56,6 +56,9 @@ namespace libtorrent struct peer_request; class peer_connection; class entry; + struct lazy_entry; + struct disk_buffer_holder; + struct bitfield; struct TORRENT_EXPORT torrent_plugin { @@ -98,14 +101,14 @@ namespace libtorrent // means that the other end doesn't support this extension and will remove // it from the list of plugins. // this is not called for web seeds - virtual bool on_handshake() { return true; } + virtual bool on_handshake(char const* reserved_bits) { return true; } // called when the extension handshake from the other end is received // if this returns false, it means that this extension isn't // supported by this peer. It will result in this peer_plugin // being removed from the peer_connection and destructed. // this is not called for web seeds - virtual bool on_extension_handshake(entry const& h) { return true; } + virtual bool on_extension_handshake(lazy_entry const& h) { return true; } // returning true from any of the message handlers // indicates that the plugin has handeled the message. @@ -128,7 +131,7 @@ namespace libtorrent virtual bool on_have(int index) { return false; } - virtual bool on_bitfield(std::vector const& bitfield) + virtual bool on_bitfield(bitfield const& bitfield) { return false; } virtual bool on_have_all() @@ -143,7 +146,7 @@ namespace libtorrent virtual bool on_request(peer_request const& req) { return false; } - virtual bool on_piece(peer_request const& piece, char const* data) + virtual bool on_piece(peer_request const& piece, disk_buffer_holder& data) { return false; } virtual bool on_cancel(peer_request const& req) diff --git a/libtorrent/include/libtorrent/allocate_resources.hpp b/libtorrent/include/libtorrent/extensions/smart_ban.hpp similarity index 56% rename from libtorrent/include/libtorrent/allocate_resources.hpp rename to libtorrent/include/libtorrent/extensions/smart_ban.hpp index 3d8237914..5d7d30c82 100644 --- a/libtorrent/include/libtorrent/allocate_resources.hpp +++ b/libtorrent/include/libtorrent/extensions/smart_ban.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2003, Magnus Jonsson +Copyright (c) 2007, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,49 +30,26 @@ POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TORRENT_ALLOCATE_RESOURCES_HPP_INCLUDED -#define TORRENT_ALLOCATE_RESOURCES_HPP_INCLUDED +#ifndef TORRENT_SMART_BAN_HPP_INCLUDED +#define TORRENT_SMART_BAN_HPP_INCLUDED -#include -#include +#ifdef _MSC_VER +#pragma warning(push, 1) +#endif #include +#include "libtorrent/config.hpp" -#include "libtorrent/resource_request.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/session.hpp" +#ifdef _MSC_VER +#pragma warning(pop) +#endif namespace libtorrent { - class peer_connection; + struct torrent_plugin; class torrent; - - int saturated_add(int a, int b); - - // Function to allocate a limited resource fairly among many consumers. - // It takes into account the current use, and the consumer's desired use. - // Should be invoked periodically to allow it adjust to the situation (make - // sure "used" is updated between calls!). - // If resources = std::numeric_limits::max() it means there is an infinite - // supply of resources (so everyone can get what they want). - - void allocate_resources( - int resources - , std::map >& torrents - , resource_request torrent::* res); - - void allocate_resources( - int resources - , std::map& connections - , resource_request peer_connection::* res); - - // Used for global limits. - void allocate_resources( - int resources - , std::vector& _sessions - , resource_request session::* res); + TORRENT_EXPORT boost::shared_ptr create_smart_ban_plugin(torrent*, void*); } +#endif // TORRENT_SMART_BAN_HPP_INCLUDED -#endif diff --git a/libtorrent/include/libtorrent/extensions/ut_metadata.hpp b/libtorrent/include/libtorrent/extensions/ut_metadata.hpp new file mode 100644 index 000000000..91437b17c --- /dev/null +++ b/libtorrent/include/libtorrent/extensions/ut_metadata.hpp @@ -0,0 +1,55 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +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. + +*/ + +#ifndef TORRENT_UT_METADATA_HPP_INCLUDED +#define TORRENT_UT_METADATA_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push, 1) +#endif + +#include +#include "libtorrent/config.hpp" + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +namespace libtorrent +{ + struct torrent_plugin; + class torrent; + TORRENT_EXPORT boost::shared_ptr create_ut_metadata_plugin(torrent*, void*); +} + +#endif // TORRENT_UT_METADATA_HPP_INCLUDED + diff --git a/libtorrent/include/libtorrent/file.hpp b/libtorrent/include/libtorrent/file.hpp old mode 100755 new mode 100644 index bd0d03539..a0d3ef1c0 --- a/libtorrent/include/libtorrent/file.hpp +++ b/libtorrent/include/libtorrent/file.hpp @@ -34,7 +34,8 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_FILE_HPP_INCLUDED #include -#include +#include +#include #ifdef _MSC_VER #pragma warning(push, 1) @@ -54,11 +55,6 @@ namespace libtorrent { namespace fs = boost::filesystem; - struct TORRENT_EXPORT file_error: std::runtime_error - { - file_error(std::string const& msg): std::runtime_error(msg) {} - }; - class TORRENT_EXPORT file: public boost::noncopyable { public: @@ -109,9 +105,9 @@ namespace libtorrent file(fs::path const& p, open_mode m); ~file(); - void open(fs::path const& p, open_mode m); + bool open(fs::path const& p, open_mode m); void close(); - void set_size(size_type size); + bool set_size(size_type size); size_type write(const char*, size_type num_bytes); size_type read(char*, size_type num_bytes); @@ -119,6 +115,8 @@ namespace libtorrent size_type seek(size_type pos, seek_mode m = begin); size_type tell(); + std::string const& error() const; + private: struct impl; diff --git a/libtorrent/include/libtorrent/file_pool.hpp b/libtorrent/include/libtorrent/file_pool.hpp index a22c26538..69116d675 100644 --- a/libtorrent/include/libtorrent/file_pool.hpp +++ b/libtorrent/include/libtorrent/file_pool.hpp @@ -65,8 +65,10 @@ namespace libtorrent { file_pool(int size = 40): m_size(size) {} - boost::shared_ptr open_file(void* st, fs::path const& p, file::open_mode m); + boost::shared_ptr open_file(void* st, fs::path const& p + , file::open_mode m, std::string& error); void release(void* st); + void release(fs::path const& p); void resize(int size); private: @@ -74,9 +76,7 @@ namespace libtorrent struct lru_file_entry { - lru_file_entry(boost::shared_ptr const& f) - : file_ptr(f) - , last_use(time_now()) {} + lru_file_entry(): last_use(time_now()) {} mutable boost::shared_ptr file_ptr; fs::path file_path; void* key; diff --git a/libtorrent/include/libtorrent/file_storage.hpp b/libtorrent/include/libtorrent/file_storage.hpp new file mode 100644 index 000000000..47fcb92eb --- /dev/null +++ b/libtorrent/include/libtorrent/file_storage.hpp @@ -0,0 +1,147 @@ +/* + +Copyright (c) 2003-2008, Arvid Norberg +All rights reserved. + +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. + +*/ + +#ifndef TORRENT_FILE_STORAGE_HPP_INCLUDED +#define TORRENT_FILE_STORAGE_HPP_INCLUDED + +#include +#include + +#ifdef _MSC_VER +#pragma warning(push, 1) +#endif + +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include "libtorrent/size_type.hpp" +#include "libtorrent/assert.hpp" +#include "libtorrent/peer_request.hpp" + +namespace libtorrent +{ + namespace fs = boost::filesystem; + + struct TORRENT_EXPORT file_entry + { + file_entry(): offset(0), size(0), file_base(0) {} + + fs::path path; + size_type offset; // the offset of this file inside the torrent + size_type size; // the size of this file + // the offset in the file where the storage starts. + // This is always 0 unless parts of the torrent is + // compressed into a single file, such as a so-called part file. + size_type file_base; + }; + + struct TORRENT_EXPORT file_slice + { + int file_index; + size_type offset; + size_type size; + }; + + class TORRENT_EXPORT file_storage + { + friend class torrent_info; + public: + file_storage(); + ~file_storage() {} + + bool is_valid() const { return m_piece_length > 0; } + + void add_file(file_entry const& e); + void add_file(fs::path const& p, size_type size); + void rename_file(int index, std::string const& new_filename); + + std::vector map_block(int piece, size_type offset + , int size) const; + peer_request map_file(int file, size_type offset, int size) const; + + typedef std::vector::const_iterator iterator; + typedef std::vector::const_reverse_iterator reverse_iterator; + + iterator file_at_offset(size_type offset) const; + iterator begin() const { return m_files.begin(); } + iterator end() const { return m_files.end(); } + reverse_iterator rbegin() const { return m_files.rbegin(); } + reverse_iterator rend() const { return m_files.rend(); } + int num_files() const + { return int(m_files.size()); } + + file_entry const& at(int index) const + { + TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + return m_files[index]; + } + + size_type total_size() const { TORRENT_ASSERT(m_piece_length > 0); return m_total_size; } + void set_num_pieces(int n) { m_num_pieces = n; } + int num_pieces() const { TORRENT_ASSERT(m_piece_length > 0); return m_num_pieces; } + void set_piece_length(int l) { m_piece_length = l; } + int piece_length() const { TORRENT_ASSERT(m_piece_length > 0); return m_piece_length; } + int piece_size(int index) const; + + void set_name(std::string const& n) { m_name = n; } + const std::string& name() const { TORRENT_ASSERT(m_piece_length > 0); return m_name; } + + void swap(file_storage& ti) + { + using std::swap; + swap(ti.m_piece_length, m_piece_length); + swap(ti.m_files, m_files); + swap(ti.m_total_size, m_total_size); + swap(ti.m_num_pieces, m_num_pieces); + swap(ti.m_name, m_name); + } + + private: + int m_piece_length; + + // the list of files that this torrent consists of + std::vector m_files; + + // the sum of all filesizes + size_type m_total_size; + + // the number of pieces in the torrent + int m_num_pieces; + std::string m_name; + }; +} + +#endif // TORRENT_FILE_STORAGE_HPP_INCLUDED + diff --git a/libtorrent/include/libtorrent/fingerprint.hpp b/libtorrent/include/libtorrent/fingerprint.hpp old mode 100755 new mode 100644 diff --git a/libtorrent/include/libtorrent/gzip.hpp b/libtorrent/include/libtorrent/gzip.hpp new file mode 100644 index 000000000..0528b58f2 --- /dev/null +++ b/libtorrent/include/libtorrent/gzip.hpp @@ -0,0 +1,43 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +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. + +*/ + +namespace libtorrent +{ + + TORRENT_EXPORT bool inflate_gzip( + char const* in, int size + , std::vector& buffer + , int maximum_size + , std::string& error); + +} + diff --git a/libtorrent/include/libtorrent/hasher.hpp b/libtorrent/include/libtorrent/hasher.hpp old mode 100755 new mode 100644 diff --git a/libtorrent/include/libtorrent/http_connection.hpp b/libtorrent/include/libtorrent/http_connection.hpp index 3ec5b3494..b13b457fa 100644 --- a/libtorrent/include/libtorrent/http_connection.hpp +++ b/libtorrent/include/libtorrent/http_connection.hpp @@ -39,19 +39,28 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include "libtorrent/socket.hpp" -#include "libtorrent/http_tracker_connection.hpp" +#include "libtorrent/http_parser.hpp" #include "libtorrent/time.hpp" #include "libtorrent/assert.hpp" +#include "libtorrent/socket_type.hpp" +#include "libtorrent/session_settings.hpp" + +#ifdef TORRENT_USE_OPENSSL +#include "libtorrent/ssl_stream.hpp" +#include "libtorrent/variant_stream.hpp" +#endif namespace libtorrent { struct http_connection; +class connection_queue; -typedef boost::function http_handler; typedef boost::function http_connect_handler; @@ -62,7 +71,7 @@ typedef boost::function http_connect_handler; // will always be 0 struct http_connection : boost::enable_shared_from_this, boost::noncopyable { - http_connection(asio::io_service& ios, connection_queue& cc + http_connection(io_service& ios, connection_queue& cc , http_handler const& handler, bool bottled = true , http_connect_handler const& ch = http_connect_handler()) : m_sock(ios) @@ -81,6 +90,9 @@ struct http_connection : boost::enable_shared_from_this, boost: , m_redirects(5) , m_connection_ticket(-1) , m_cc(cc) + , m_ssl(false) + , m_priority(0) + , m_abort(false) { TORRENT_ASSERT(!m_handler.empty()); } @@ -93,32 +105,44 @@ struct http_connection : boost::enable_shared_from_this, boost: std::string sendbuffer; void get(std::string const& url, time_duration timeout = seconds(30) - , int handle_redirects = 5); + , int prio = 0, proxy_settings const* ps = 0, int handle_redirects = 5 + , std::string const& user_agent = "", address const& bind_addr = address_v4::any()); void start(std::string const& hostname, std::string const& port - , time_duration timeout, int handle_redirect = 5); + , time_duration timeout, int prio = 0, proxy_settings const* ps = 0 + , bool ssl = false, int handle_redirect = 5 + , address const& bind_addr = address_v4::any()); + void close(); - tcp::socket const& socket() const { return m_sock; } - +#ifdef TORRENT_USE_OPENSSL + variant_stream > const& socket() const { return m_sock; } +#else + socket_type const& socket() const { return m_sock; } +#endif + private: - void on_resolve(asio::error_code const& e + void on_resolve(error_code const& e , tcp::resolver::iterator i); + void queue_connect(); void connect(int ticket, tcp::endpoint target_address); void on_connect_timeout(); - void on_connect(asio::error_code const& e -/* , tcp::resolver::iterator i*/); - void on_write(asio::error_code const& e); - void on_read(asio::error_code const& e, std::size_t bytes_transferred); + void on_connect(error_code const& e); + void on_write(error_code const& e); + void on_read(error_code const& e, std::size_t bytes_transferred); static void on_timeout(boost::weak_ptr p - , asio::error_code const& e); - void on_assign_bandwidth(asio::error_code const& e); + , error_code const& e); + void on_assign_bandwidth(error_code const& e); - void callback(asio::error_code const& e, char const* data = 0, int size = 0); + void callback(error_code const& e, char const* data = 0, int size = 0); std::vector m_recvbuffer; - tcp::socket m_sock; +#ifdef TORRENT_USE_OPENSSL + variant_stream > m_sock; +#else + socket_type m_sock; +#endif int m_read_pos; tcp::resolver m_resolver; http_parser m_parser; @@ -138,6 +162,8 @@ private: std::string m_port; std::string m_url; + std::list m_endpoints; + // the current download limit, in bytes per second // 0 is unlimited. int m_rate_limit; @@ -159,6 +185,23 @@ private: int m_connection_ticket; connection_queue& m_cc; + + // specifies whether or not the connection is + // configured to use a proxy + proxy_settings m_proxy; + + // true if the connection is using ssl + bool m_ssl; + + // the address to bind to. address_v4::any() + // means do not bind + address m_bind_addr; + + // the priority we have in the connection queue. + // 0 is normal, 1 is high + int m_priority; + + bool m_abort; }; } diff --git a/libtorrent/include/libtorrent/http_parser.hpp b/libtorrent/include/libtorrent/http_parser.hpp new file mode 100644 index 000000000..7d308ca36 --- /dev/null +++ b/libtorrent/include/libtorrent/http_parser.hpp @@ -0,0 +1,111 @@ +/* + +Copyright (c) 2008, Arvid Norberg +All rights reserved. + +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. + +*/ + +#ifndef TORRENT_HTTP_PARSER_HPP_INCLUDED +#define TORRENT_HTTP_PARSER_HPP_INCLUDED + +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(push, 1) +#endif + +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include "libtorrent/config.hpp" +#include "libtorrent/buffer.hpp" +#include "libtorrent/size_type.hpp" + +namespace libtorrent +{ + + class http_parser + { + public: + http_parser(); + std::string const& header(char const* key) const + { + static std::string empty; + std::map::const_iterator i + = m_header.find(key); + if (i == m_header.end()) return empty; + return i->second; + } + + std::string const& protocol() const { return m_protocol; } + int status_code() const { return m_status_code; } + std::string const& method() const { return m_method; } + std::string const& path() const { return m_path; } + std::string const& message() const { return m_server_message; } + buffer::const_interval get_body() const; + bool header_finished() const { return m_state == read_body; } + bool finished() const { return m_finished; } + boost::tuple incoming(buffer::const_interval recv_buffer + , bool& error); + int body_start() const { return m_body_start_pos; } + size_type content_length() const { return m_content_length; } + + void reset(); + + std::map const& headers() const { return m_header; } + + private: + int m_recv_pos; + int m_status_code; + std::string m_method; + std::string m_path; + std::string m_protocol; + std::string m_server_message; + + size_type m_content_length; + + enum { read_status, read_header, read_body, error_state } m_state; + + std::map m_header; + buffer::const_interval m_recv_buffer; + int m_body_start_pos; + + bool m_finished; + }; + +} + +#endif // TORRENT_HTTP_PARSER_HPP_INCLUDED + diff --git a/libtorrent/include/libtorrent/http_stream.hpp b/libtorrent/include/libtorrent/http_stream.hpp index 041b7c84f..db1602120 100644 --- a/libtorrent/include/libtorrent/http_stream.hpp +++ b/libtorrent/include/libtorrent/http_stream.hpp @@ -41,7 +41,7 @@ class http_stream : public proxy_base { public: - explicit http_stream(asio::io_service& io_service) + explicit http_stream(io_service& io_service) : proxy_base(io_service) , m_no_connect(false) {} @@ -55,7 +55,7 @@ public: m_password = password; } - typedef boost::function handler_type; + typedef boost::function handler_type; template void async_connect(endpoint_type const& endpoint, Handler const& handler) @@ -80,11 +80,11 @@ public: private: - void name_lookup(asio::error_code const& e, tcp::resolver::iterator i + void name_lookup(error_code const& e, tcp::resolver::iterator i , boost::shared_ptr h); - void connected(asio::error_code const& e, boost::shared_ptr h); - void handshake1(asio::error_code const& e, boost::shared_ptr h); - void handshake2(asio::error_code const& e, boost::shared_ptr h); + void connected(error_code const& e, boost::shared_ptr h); + void handshake1(error_code const& e, boost::shared_ptr h); + void handshake2(error_code const& e, boost::shared_ptr h); // send and receive buffer std::vector m_buffer; diff --git a/libtorrent/include/libtorrent/http_tracker_connection.hpp b/libtorrent/include/libtorrent/http_tracker_connection.hpp old mode 100755 new mode 100644 index 41df4c953..04701fc00 --- a/libtorrent/include/libtorrent/http_tracker_connection.hpp +++ b/libtorrent/include/libtorrent/http_tracker_connection.hpp @@ -33,85 +33,30 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED #define TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED -#include #include -#include -#include #ifdef _MSC_VER #pragma warning(push, 1) #endif #include -#include -#include -#include #ifdef _MSC_VER #pragma warning(pop) #endif -#include "libtorrent/socket.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session_settings.hpp" #include "libtorrent/peer_id.hpp" -#include "libtorrent/peer.hpp" #include "libtorrent/tracker_manager.hpp" #include "libtorrent/config.hpp" -#include "libtorrent/buffer.hpp" -#include "libtorrent/socket_type.hpp" -#include "libtorrent/connection_queue.hpp" namespace libtorrent { - class http_parser - { - public: - http_parser(); - std::string const& header(char const* key) const - { - static std::string empty; - std::map::const_iterator i - = m_header.find(key); - if (i == m_header.end()) return empty; - return i->second; - } - - std::string const& protocol() const { return m_protocol; } - int status_code() const { return m_status_code; } - std::string const& method() const { return m_method; } - std::string const& path() const { return m_path; } - std::string const& message() const { return m_server_message; } - buffer::const_interval get_body() const; - bool header_finished() const { return m_state == read_body; } - bool finished() const { return m_finished; } - boost::tuple incoming(buffer::const_interval recv_buffer); - int body_start() const { return m_body_start_pos; } - int content_length() const { return m_content_length; } - - void reset(); - - std::map const& headers() const { return m_header; } - - private: - int m_recv_pos; - int m_status_code; - std::string m_method; - std::string m_path; - std::string m_protocol; - std::string m_server_message; - - int m_content_length; - - enum { read_status, read_header, read_body } m_state; - - std::map m_header; - buffer::const_interval m_recv_buffer; - int m_body_start_pos; - - bool m_finished; - }; + struct http_connection; + class entry; + class http_parser; + class connection_queue; + struct session_settings; class TORRENT_EXPORT http_tracker_connection : public tracker_connection @@ -120,13 +65,10 @@ namespace libtorrent public: http_tracker_connection( - asio::strand& str + io_service& ios , connection_queue& cc , tracker_manager& man , tracker_request const& req - , std::string const& hostname - , unsigned short port - , std::string request , address bind_infc , boost::weak_ptr c , session_settings const& stn @@ -140,43 +82,16 @@ namespace libtorrent boost::intrusive_ptr self() { return boost::intrusive_ptr(this); } - void on_response(); - - void init_send_buffer( - std::string const& hostname - , std::string const& request); + void on_response(error_code const& ec, http_parser const& parser + , char const* data, int size); - void name_lookup(asio::error_code const& error, tcp::resolver::iterator i); - void connect(int ticket, tcp::endpoint target_address); - void connected(asio::error_code const& error); - void sent(asio::error_code const& error); - void receive(asio::error_code const& error - , std::size_t bytes_transferred); + virtual void on_timeout() {} - virtual void on_timeout(); - - void parse(const entry& e); - peer_entry extract_peer_info(const entry& e); + void parse(int status_code, const entry& e); + bool extract_peer_info(const entry& e, peer_entry& ret); tracker_manager& m_man; - http_parser m_parser; - - asio::strand& m_strand; - tcp::resolver m_name_lookup; - int m_port; - socket_type m_socket; - int m_recv_pos; - std::vector m_buffer; - std::string m_send_buffer; - - session_settings const& m_settings; - proxy_settings const& m_proxy; - std::string m_password; - - bool m_timed_out; - - int m_connection_ticket; - connection_queue& m_cc; + boost::shared_ptr m_tracker_connection; }; } diff --git a/libtorrent/include/libtorrent/identify_client.hpp b/libtorrent/include/libtorrent/identify_client.hpp old mode 100755 new mode 100644 diff --git a/libtorrent/include/libtorrent/instantiate_connection.hpp b/libtorrent/include/libtorrent/instantiate_connection.hpp index 71282f993..26efcd6cf 100644 --- a/libtorrent/include/libtorrent/instantiate_connection.hpp +++ b/libtorrent/include/libtorrent/instantiate_connection.hpp @@ -34,14 +34,13 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_INSTANTIATE_CONNECTION #include "libtorrent/socket_type.hpp" -#include #include namespace libtorrent { struct proxy_settings; - bool instantiate_connection(asio::io_service& ios + bool instantiate_connection(io_service& ios , proxy_settings const& ps, socket_type& s); } diff --git a/libtorrent/include/libtorrent/intrusive_ptr_base.hpp b/libtorrent/include/libtorrent/intrusive_ptr_base.hpp index 5cccdf827..c2f4e5b60 100644 --- a/libtorrent/include/libtorrent/intrusive_ptr_base.hpp +++ b/libtorrent/include/libtorrent/intrusive_ptr_base.hpp @@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include "libtorrent/config.hpp" #include "libtorrent/assert.hpp" diff --git a/libtorrent/include/libtorrent/invariant_check.hpp b/libtorrent/include/libtorrent/invariant_check.hpp old mode 100755 new mode 100644 diff --git a/libtorrent/include/libtorrent/io.hpp b/libtorrent/include/libtorrent/io.hpp old mode 100755 new mode 100644 diff --git a/libtorrent/include/libtorrent/kademlia/closest_nodes.hpp b/libtorrent/include/libtorrent/kademlia/closest_nodes.hpp index 244e4bb38..bd4771ea4 100644 --- a/libtorrent/include/libtorrent/kademlia/closest_nodes.hpp +++ b/libtorrent/include/libtorrent/kademlia/closest_nodes.hpp @@ -68,7 +68,7 @@ public: private: void done(); - void invoke(node_id const& id, asio::ip::udp::endpoint addr); + void invoke(node_id const& id, udp::endpoint addr); closest_nodes( node_id target diff --git a/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp b/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp index 6882d34bb..ef07b1b91 100644 --- a/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp +++ b/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp @@ -50,9 +50,10 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/kademlia/node.hpp" #include "libtorrent/kademlia/node_id.hpp" #include "libtorrent/kademlia/traversal_algorithm.hpp" -#include "libtorrent/kademlia/packet_iterator.hpp" #include "libtorrent/session_settings.hpp" #include "libtorrent/session_status.hpp" +#include "libtorrent/udp_socket.hpp" +#include "libtorrent/socket.hpp" namespace libtorrent { namespace dht { @@ -70,16 +71,14 @@ namespace libtorrent { namespace dht { friend void intrusive_ptr_add_ref(dht_tracker const*); friend void intrusive_ptr_release(dht_tracker const*); - dht_tracker(asio::io_service& ios, dht_settings const& settings - , asio::ip::address listen_interface, entry const& bootstrap); + dht_tracker(udp_socket& sock, dht_settings const& settings + , entry const& bootstrap); void stop(); void add_node(udp::endpoint node); void add_node(std::pair const& node); void add_router_node(std::pair const& node); - void rebind(asio::ip::address listen_interface, int listen_port); - entry state() const; void announce(sha1_hash const& ih, int listen_port @@ -88,35 +87,30 @@ namespace libtorrent { namespace dht void dht_status(session_status& s); + // translate bittorrent kademlia message into the generic kademlia message + // used by the library + void on_receive(udp::endpoint const& ep, char const* pkt, int size); + void on_unreachable(udp::endpoint const& ep); + private: boost::intrusive_ptr self() { return boost::intrusive_ptr(this); } - void on_name_lookup(asio::error_code const& e + void on_name_lookup(error_code const& e , udp::resolver::iterator host); - void on_router_name_lookup(asio::error_code const& e + void on_router_name_lookup(error_code const& e , udp::resolver::iterator host); - void connection_timeout(asio::error_code const& e); - void refresh_timeout(asio::error_code const& e); - void tick(asio::error_code const& e); + void connection_timeout(error_code const& e); + void refresh_timeout(error_code const& e); + void tick(error_code const& e); - // translate bittorrent kademlia message into the generic kademlia message - // used by the library - void on_receive(asio::error_code const& error, size_t bytes_transferred); void on_bootstrap(); void send_packet(msg const& m); - asio::strand m_strand; - asio::ip::udp::socket m_socket; - node_impl m_dht; + udp_socket& m_sock; - // this is the index of the receive buffer we are currently receiving to - // the other buffer is the one containing the last message - int m_buffer; - std::vector m_in_buf[2]; - udp::endpoint m_remote_endpoint[2]; std::vector m_send_buf; ptime m_last_new_key; diff --git a/libtorrent/include/libtorrent/kademlia/find_data.hpp b/libtorrent/include/libtorrent/kademlia/find_data.hpp index 17d77c9d8..7772ca7c3 100644 --- a/libtorrent/include/libtorrent/kademlia/find_data.hpp +++ b/libtorrent/include/libtorrent/kademlia/find_data.hpp @@ -39,7 +39,6 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include #include #include @@ -49,8 +48,6 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { namespace dht { -using asio::ip::udp; - typedef std::vector packet_t; class rpc_manager; diff --git a/libtorrent/include/libtorrent/kademlia/msg.hpp b/libtorrent/include/libtorrent/kademlia/msg.hpp index a205ce463..00db7305c 100644 --- a/libtorrent/include/libtorrent/kademlia/msg.hpp +++ b/libtorrent/include/libtorrent/kademlia/msg.hpp @@ -36,15 +36,17 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include "libtorrent/entry.hpp" +#if BOOST_VERSION < 103500 #include +#else +#include +#endif namespace libtorrent { namespace dht { typedef std::vector packet_t; -using asio::ip::udp; - namespace messages { enum { ping = 0, find_node = 1, get_peers = 2, announce_peer = 3, error = 4 }; diff --git a/libtorrent/include/libtorrent/kademlia/node.hpp b/libtorrent/include/libtorrent/kademlia/node.hpp index d93872db9..88a1677f1 100644 --- a/libtorrent/include/libtorrent/kademlia/node.hpp +++ b/libtorrent/include/libtorrent/kademlia/node.hpp @@ -56,8 +56,6 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { namespace dht { -using asio::ip::udp; - #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_DECLARE_LOG(node); #endif @@ -174,6 +172,7 @@ public: void(std::vector const&)> f); void add_router_node(udp::endpoint router); + void unreachable(udp::endpoint const& ep); void incoming(msg const& m); void refresh(); diff --git a/libtorrent/include/libtorrent/kademlia/node_entry.hpp b/libtorrent/include/libtorrent/kademlia/node_entry.hpp index edc5dff80..e31a60e3f 100644 --- a/libtorrent/include/libtorrent/kademlia/node_entry.hpp +++ b/libtorrent/include/libtorrent/kademlia/node_entry.hpp @@ -41,20 +41,33 @@ namespace libtorrent { namespace dht struct node_entry { - node_entry(node_id const& id_, asio::ip::udp::endpoint addr_) + node_entry(node_id const& id_, udp::endpoint addr_) : id(id_) , addr(addr_) - , fail_count(0) {} - node_entry(asio::ip::udp::endpoint addr_) + , fail_count(0) + { +#ifdef TORRENT_DHT_VERBOSE_LOGGING + first_seen = time_now(); +#endif + } + node_entry(udp::endpoint addr_) : id(0) , addr(addr_) - , fail_count(0) {} + , fail_count(0) + { +#ifdef TORRENT_DHT_VERBOSE_LOGGING + first_seen = time_now(); +#endif + } node_id id; udp::endpoint addr; // the number of times this node has failed to // respond in a row int fail_count; +#ifdef TORRENT_DHT_VERBOSE_LOGGING + ptime first_seen; +#endif }; } } // namespace libtorrent::dht diff --git a/libtorrent/include/libtorrent/kademlia/routing_table.hpp b/libtorrent/include/libtorrent/kademlia/routing_table.hpp index acb4c1885..e3f2e7ded 100644 --- a/libtorrent/include/libtorrent/kademlia/routing_table.hpp +++ b/libtorrent/include/libtorrent/kademlia/routing_table.hpp @@ -55,9 +55,10 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { namespace dht { -using asio::ip::udp; +#ifdef TORRENT_DHT_VERBOSE_LOGGING +TORRENT_DECLARE_LOG(table); +#endif -//TORRENT_DECLARE_LOG(table); typedef std::vector bucket_t; diff --git a/libtorrent/include/libtorrent/kademlia/rpc_manager.hpp b/libtorrent/include/libtorrent/kademlia/rpc_manager.hpp index a7c47f29a..837c091dd 100644 --- a/libtorrent/include/libtorrent/kademlia/rpc_manager.hpp +++ b/libtorrent/include/libtorrent/kademlia/rpc_manager.hpp @@ -44,7 +44,6 @@ POSSIBILITY OF SUCH DAMAGE. #include #include -#include #include #include #include @@ -57,7 +56,6 @@ namespace libtorrent { namespace dht struct observer; -using asio::ip::udp; #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_DECLARE_LOG(rpc); #endif @@ -83,6 +81,8 @@ public: , routing_table& table, send_fun const& sf); ~rpc_manager(); + void unreachable(udp::endpoint const& ep); + // returns true if the node needs a refresh bool incoming(msg const&); time_duration tick(); @@ -94,6 +94,7 @@ public: void reply_with_ping(msg& m); #ifndef NDEBUG + size_t allocation_size() const; void check_invariant() const; #endif @@ -114,7 +115,7 @@ private: typedef boost::array transactions_t; transactions_t m_transactions; - std::vector m_aborted_transactions; + std::vector m_aborted_transactions; // this is the next transaction id to be used int m_next_transaction_id; diff --git a/libtorrent/include/libtorrent/lazy_entry.hpp b/libtorrent/include/libtorrent/lazy_entry.hpp new file mode 100644 index 000000000..ffd4337e4 --- /dev/null +++ b/libtorrent/include/libtorrent/lazy_entry.hpp @@ -0,0 +1,232 @@ +/* + +Copyright (c) 2003, Arvid Norberg +All rights reserved. + +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. + +*/ + +#ifndef TORRENT_LAZY_ENTRY_HPP_INCLUDED +#define TORRENT_LAZY_ENTRY_HPP_INCLUDED + +#include +#include +#include "libtorrent/assert.hpp" +#include "libtorrent/size_type.hpp" +#include + +namespace libtorrent +{ + struct lazy_entry; + + char const* parse_int(char const* start, char const* end, char delimiter, boost::int64_t& val); + // return 0 = success + int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit = 1000); + + struct lazy_entry + { + enum entry_type_t + { + none_t, dict_t, list_t, string_t, int_t + }; + + lazy_entry() : m_type(none_t), m_begin(0), m_end(0) + { m_data.start = 0; } + + entry_type_t type() const { return m_type; } + + // start points to the first decimal digit + // length is the number of digits + void construct_int(char const* start, int length) + { + TORRENT_ASSERT(m_type == none_t); + m_type = int_t; + m_data.start = start; + m_size = length; + m_begin = start - 1; // include 'i' + m_end = start + length + 1; // include 'e' + } + + size_type int_value() const; + + // string functions + // ================ + + void construct_string(char const* start, int length); + + // the string is not null-terminated! + char const* string_ptr() const + { + TORRENT_ASSERT(m_type == string_t); + return m_data.start; + } + + // this will return a null terminated string + // it will write to the source buffer! + char const* string_cstr() const + { + TORRENT_ASSERT(m_type == string_t); + const_cast(m_data.start)[m_size] = 0; + return m_data.start; + } + + std::string string_value() const + { + TORRENT_ASSERT(m_type == string_t); + return std::string(m_data.start, m_size); + } + + int string_length() const + { return m_size; } + + // dictionary functions + // ==================== + + void construct_dict(char const* begin) + { + TORRENT_ASSERT(m_type == none_t); + m_type = dict_t; + m_size = 0; + m_capacity = 0; + m_begin = begin; + } + + lazy_entry* dict_append(char const* name); + lazy_entry* dict_find(char const* name); + lazy_entry const* dict_find(char const* name) const + { return const_cast(this)->dict_find(name); } + + std::string dict_find_string_value(char const* name) const; + size_type dict_find_int_value(char const* name, size_type default_val = 0) const; + lazy_entry const* dict_find_dict(char const* name) const; + lazy_entry const* dict_find_list(char const* name) const; + + std::pair dict_at(int i) const + { + TORRENT_ASSERT(m_type == dict_t); + TORRENT_ASSERT(i < m_size); + std::pair const& e = m_data.dict[i]; + return std::make_pair(std::string(e.first, e.second.m_begin - e.first), &e.second); + } + + int dict_size() const + { + TORRENT_ASSERT(m_type == dict_t); + return m_size; + } + + // list functions + // ============== + + void construct_list(char const* begin) + { + TORRENT_ASSERT(m_type == none_t); + m_type = list_t; + m_size = 0; + m_capacity = 0; + m_begin = begin; + } + + lazy_entry* list_append(); + lazy_entry* list_at(int i) + { + TORRENT_ASSERT(m_type == list_t); + TORRENT_ASSERT(i < m_size); + return &m_data.list[i]; + } + lazy_entry const* list_at(int i) const + { return const_cast(this)->list_at(i); } + + std::string list_string_value_at(int i) const; + size_type list_int_value_at(int i, size_type default_val = 0) const; + + int list_size() const + { + TORRENT_ASSERT(m_type == list_t); + return m_size; + } + + // end points one byte passed last byte + void set_end(char const* end) + { + TORRENT_ASSERT(end > m_begin); + m_end = end; + } + + void clear(); + + // releases ownership of any memory allocated + void release() + { + m_data.start = 0; + m_size = 0; + m_capacity = 0; + m_type = none_t; + } + + ~lazy_entry() + { clear(); } + + // returns pointers into the source buffer where + // this entry has its bencoded data + std::pair data_section() const; + + void swap(lazy_entry& e) + { + using std::swap; + swap(m_type, e.m_type); + swap(m_data.start, e.m_data.start); + swap(m_size, e.m_size); + swap(m_capacity, e.m_capacity); + swap(m_begin, e.m_begin); + swap(m_end, e.m_end); + } + + private: + + entry_type_t m_type; + union data_t + { + std::pair* dict; + lazy_entry* list; + char const* start; + } m_data; + int m_size; // if list or dictionary, the number of items + int m_capacity; // if list or dictionary, allocated number of items + // used for dictionaries and lists to record the range + // in the original buffer they are based on + char const* m_begin; + char const* m_end; + }; + + std::ostream& operator<<(std::ostream& os, lazy_entry const& e); + +}; + + +#endif + diff --git a/libtorrent/include/libtorrent/lsd.hpp b/libtorrent/include/libtorrent/lsd.hpp index 6fb6b7c7b..6e3ddea7d 100644 --- a/libtorrent/include/libtorrent/lsd.hpp +++ b/libtorrent/include/libtorrent/lsd.hpp @@ -67,7 +67,7 @@ public: private: - void resend_announce(asio::error_code const& e, std::string msg); + void resend_announce(error_code const& e, std::string msg); void on_announce(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred); // void setup_receive(); diff --git a/libtorrent/include/libtorrent/magnet_uri.hpp b/libtorrent/include/libtorrent/magnet_uri.hpp new file mode 100644 index 000000000..2e947efa0 --- /dev/null +++ b/libtorrent/include/libtorrent/magnet_uri.hpp @@ -0,0 +1,59 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +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. + +*/ + +#ifndef TORRENT_MAGNET_URI_HPP_INCLUDED +#define TORRENT_MAGNET_URI_HPP_INCLUDED + +#include +#include "libtorrent/config.hpp" +#include "libtorrent/torrent_handle.hpp" +#include "libtorrent/session.hpp" +#include + +namespace libtorrent +{ + namespace fs = boost::filesystem; + + struct torrent_handle; + + std::string TORRENT_EXPORT make_magnet_uri(torrent_handle const& handle); + + torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::string const& uri + , fs::path const& save_path + , storage_mode_t storage_mode = storage_mode_sparse + , bool paused = false + , storage_constructor_type sc = default_storage_constructor + , void* userdata = 0); +} + +#endif + diff --git a/libtorrent/include/libtorrent/natpmp.hpp b/libtorrent/include/libtorrent/natpmp.hpp index 3b9923972..8ce54132b 100644 --- a/libtorrent/include/libtorrent/natpmp.hpp +++ b/libtorrent/include/libtorrent/natpmp.hpp @@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/intrusive_ptr_base.hpp" #include +#include #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) #include @@ -45,8 +46,8 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { -// int: external tcp port -// int: external udp port +// int: port mapping index +// int: external port // std::string: error message typedef boost::function portmap_callback_t; @@ -59,34 +60,38 @@ public: // maps the ports, if a port is set to 0 // it will not be mapped - void set_mappings(int tcp, int udp); + enum protocol_type { none = 0, udp = 1, tcp = 2 }; + int add_mapping(protocol_type p, int external_port, int local_port); + void delete_mapping(int mapping_index); void close(); private: - void update_mapping(int i, int port); + void update_mapping(int i); void send_map_request(int i); - void resend_request(int i, asio::error_code const& e); - void on_reply(asio::error_code const& e + void resend_request(int i, error_code const& e); + void on_reply(error_code const& e , std::size_t bytes_transferred); void try_next_mapping(int i); void update_expiration_timer(); - void refresh_mapping(int i); - void mapping_expired(asio::error_code const& e, int i); + void mapping_expired(error_code const& e, int i); - struct mapping + void disable(char const* message); + + struct mapping_t { - mapping() - : need_update(false) + enum action_t { action_none, action_add, action_delete }; + mapping_t() + : action(action_none) , local_port(0) , external_port(0) - , protocol(1) + , protocol(none) {} // indicates that the mapping has changed // and needs an update - bool need_update; + int action; // the time the port mapping will expire ptime expires; @@ -100,14 +105,12 @@ private: // should announce to others int external_port; - // 1 = udp, 2 = tcp int protocol; }; portmap_callback_t m_callback; - // 0 is tcp and 1 is udp - mapping m_mappings[2]; + std::vector m_mappings; // the endpoint to the nat router udp::endpoint m_nat_endpoint; @@ -136,9 +139,17 @@ private: // timer used to refresh mappings deadline_timer m_refresh_timer; + + // the mapping index that will expire next + int m_next_refresh; bool m_disabled; + bool m_abort; + + typedef boost::mutex mutex_t; + mutex_t m_mutex; + #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) std::ofstream m_log; #endif diff --git a/libtorrent/include/libtorrent/resource_request.hpp b/libtorrent/include/libtorrent/parse_url.hpp old mode 100755 new mode 100644 similarity index 56% rename from libtorrent/include/libtorrent/resource_request.hpp rename to libtorrent/include/libtorrent/parse_url.hpp index 1e41b9cbb..18a6ddf90 --- a/libtorrent/include/libtorrent/resource_request.hpp +++ b/libtorrent/include/libtorrent/parse_url.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2003, Magnus Jonsson, Arvid Norberg +Copyright (c) 2008, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,70 +30,30 @@ POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TORRENT_RESOURCE_REQUEST_HPP_INCLUDED -#define TORRENT_RESOURCE_REQUEST_HPP_INCLUDED +#ifndef TORRENT_PARSE_URL_HPP_INCLUDED +#define TORRENT_PARSE_URL_HPP_INCLUDED -#include - -#ifdef min -#undef min +#ifdef _MSC_VER +#pragma warning(push, 1) #endif -#ifdef max -#undef max +#include + +#ifdef _MSC_VER +#pragma warning(pop) #endif +#include #include "libtorrent/config.hpp" namespace libtorrent { - struct TORRENT_EXPORT resource_request - { - resource_request() - : used(0) - , min(0) - , max(0) - , given(0) - , leftovers(0) - {} - resource_request(int used_, int min_, int max_, int given_) - : used(used_) - , min(min_) - , max(max_) - , given(given_) - , leftovers(0) - {} + TORRENT_EXPORT boost::tuple + parse_url_components(std::string url); - int left() const - { - assert(given <= max); - assert(given >= min); - assert(used >= 0); - return (std::max)(given - used, 0); - } - - void reset() { used = leftovers; leftovers = 0; } - - static const int inf = boost::integer_traits::const_max; - - // right now I'm actively using this amount - int used; - - // given cannot be smaller than min - // and not greater than max. - int min; - int max; - - // Reply: Okay, you're allowed to use this amount (a compromise): - int given; - - // this is the amount of resources that exceeded the - // given limit. When the used field is reset (after resources - // have been distributed), it is reset to this number. - int leftovers; - }; } - #endif + diff --git a/libtorrent/include/libtorrent/pch.hpp b/libtorrent/include/libtorrent/pch.hpp index 735999826..de937c596 100644 --- a/libtorrent/include/libtorrent/pch.hpp +++ b/libtorrent/include/libtorrent/pch.hpp @@ -1,3 +1,35 @@ +/* + +Copyright (c) 2008, Arvid Norberg +All rights reserved. + +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. + +*/ + #ifdef BOOST_BUILD_PCH_ENABLED #include @@ -86,7 +118,6 @@ #include #include #include -#include #ifdef __OBJC__ #undef Protocol diff --git a/libtorrent/include/libtorrent/pe_crypto.hpp b/libtorrent/include/libtorrent/pe_crypto.hpp index 5db77f6c7..dd1260497 100644 --- a/libtorrent/include/libtorrent/pe_crypto.hpp +++ b/libtorrent/include/libtorrent/pe_crypto.hpp @@ -44,31 +44,30 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { - class DH_key_exchange + class dh_key_exchange { public: - DH_key_exchange (); - ~DH_key_exchange (); + dh_key_exchange(); + ~dh_key_exchange(); + bool good() const { return m_dh; } // Get local public key, always 96 bytes - char const* get_local_key (void) const; + char const* get_local_key() const; // read remote_pubkey, generate and store shared secret in - // m_dh_secret - void compute_secret (const char* remote_pubkey); + // m_dh_secret. + int compute_secret(const char* remote_pubkey); - const char* get_secret (void) const; + const char* get_secret() const; private: - int get_local_key_size () const + int get_local_key_size() const { - TORRENT_ASSERT(m_DH); - return BN_num_bytes (m_DH->pub_key); + TORRENT_ASSERT(m_dh); + return BN_num_bytes(m_dh->pub_key); } - DH* m_DH; - static const unsigned char m_dh_prime[96]; - static const unsigned char m_dh_generator[1]; + DH* m_dh; char m_dh_local_key[96]; char m_dh_secret[96]; @@ -78,24 +77,24 @@ namespace libtorrent { public: // Input longkeys must be 20 bytes - RC4_handler (const sha1_hash& rc4_local_longkey, + RC4_handler(const sha1_hash& rc4_local_longkey, const sha1_hash& rc4_remote_longkey) { - RC4_set_key (&m_local_key, 20, + RC4_set_key(&m_local_key, 20, reinterpret_cast(rc4_local_longkey.begin())); - RC4_set_key (&m_remote_key, 20, + RC4_set_key(&m_remote_key, 20, reinterpret_cast(rc4_remote_longkey.begin())); // Discard first 1024 bytes char buf[1024]; - encrypt (buf, 1024); - decrypt (buf, 1024); + encrypt(buf, 1024); + decrypt(buf, 1024); }; - ~RC4_handler () {}; + ~RC4_handler() {}; - void encrypt (char* pos, int len) + void encrypt(char* pos, int len) { TORRENT_ASSERT(len >= 0); TORRENT_ASSERT(pos); @@ -104,7 +103,7 @@ namespace libtorrent reinterpret_cast(pos)); } - void decrypt (char* pos, int len) + void decrypt(char* pos, int len) { TORRENT_ASSERT(len >= 0); TORRENT_ASSERT(pos); @@ -122,3 +121,4 @@ namespace libtorrent #endif // TORRENT_PE_CRYPTO_HPP_INCLUDED #endif // TORRENT_DISABLE_ENCRYPTION + diff --git a/libtorrent/include/libtorrent/peer.hpp b/libtorrent/include/libtorrent/peer.hpp old mode 100755 new mode 100644 diff --git a/libtorrent/include/libtorrent/peer_connection.hpp b/libtorrent/include/libtorrent/peer_connection.hpp old mode 100755 new mode 100644 index 69545fd76..5a24e433d --- a/libtorrent/include/libtorrent/peer_connection.hpp +++ b/libtorrent/include/libtorrent/peer_connection.hpp @@ -75,6 +75,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/assert.hpp" #include "libtorrent/chained_buffer.hpp" +#include "libtorrent/disk_buffer_holder.hpp" +#include "libtorrent/bitfield.hpp" namespace libtorrent { @@ -86,9 +88,21 @@ namespace libtorrent struct session_impl; } - struct TORRENT_EXPORT protocol_error: std::runtime_error + struct pending_block { - protocol_error(const std::string& msg): std::runtime_error(msg) {}; + pending_block(piece_block const& b): skipped(0), block(b) {} + int skipped; + // the number of times the request + // has been skipped by out of order blocks + piece_block block; + }; + + struct has_block + { + has_block(piece_block const& b): block(b) {} + piece_block const& block; + bool operator()(pending_block const& pb) const + { return pb.block == block; } }; class TORRENT_EXPORT peer_connection @@ -123,6 +137,12 @@ namespace libtorrent , tcp::endpoint const& remote , policy::peer* peerinfo); + // this function is called after it has been constructed and properly + // reference counted. It is safe to call self() in this function + // and schedule events with references to itself (that is not safe to + // do in the constructor). + virtual void start(); + virtual ~peer_connection(); void set_peer_info(policy::peer* pi) @@ -191,7 +211,8 @@ namespace libtorrent bool is_seed() const; - bool has_timed_out() const; + void set_upload_only(bool u) { m_upload_only = u; } + bool upload_only() const { return m_upload_only; } // will send a keep-alive message to the peer void keep_alive(); @@ -200,7 +221,7 @@ namespace libtorrent void set_pid(const peer_id& pid) { m_peer_id = pid; } bool has_piece(int i) const; - std::deque const& download_queue() const; + std::deque const& download_queue() const; std::deque const& request_queue() const; std::deque const& upload_queue() const; @@ -224,25 +245,32 @@ namespace libtorrent const stat& statistics() const { return m_statistics; } void add_stat(size_type downloaded, size_type uploaded); + void calc_ip_overhead(); + // is called once every second by the main loop void second_tick(float tick_interval); + void timeout_requests(); + boost::shared_ptr get_socket() const { return m_socket; } tcp::endpoint const& remote() const { return m_remote; } - std::vector const& get_bitfield() const; + bitfield const& get_bitfield() const; std::vector const& allowed_fast(); std::vector const& suggested_pieces() const { return m_suggested_pieces; } + ptime connected_time() const { return m_connect; } + ptime last_received() const { return m_last_receive; } + void timed_out(); // this will cause this peer_connection to be disconnected. - void disconnect(); + void disconnect(char const* message, int error = 0); bool is_disconnecting() const { return m_disconnecting; } // this is called when the connection attempt has succeeded // and the peer_connection is supposed to set m_connecting // to false, and stop monitor writability - void on_connection_complete(asio::error_code const& e); + void on_connection_complete(error_code const& e); // returns true if this connection is still waiting to // finish the connection attempt @@ -282,12 +310,20 @@ namespace libtorrent bool ignore_bandwidth_limits() const { return m_ignore_bandwidth_limits; } - void set_failed() { m_failed = true; } bool failed() const { return m_failed; } int desired_queue_size() const { return m_desired_queue_size; } -#ifdef TORRENT_VERBOSE_LOGGING + // compares this connection against the given connection + // for which one is more eligible for an unchoke. + // returns true if this is more eligible + bool unchoke_compare(boost::intrusive_ptr const& p) const; + + // resets the byte counters that are used to measure + // the number of bytes transferred within unchoke cycles + void reset_choke_counters(); + +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING boost::shared_ptr m_logger; #endif @@ -305,8 +341,9 @@ namespace libtorrent void incoming_interested(); void incoming_not_interested(); void incoming_have(int piece_index); - void incoming_bitfield(std::vector const& bitfield); + void incoming_bitfield(bitfield const& bits); void incoming_request(peer_request const& r); + void incoming_piece(peer_request const& p, disk_buffer_holder& data); void incoming_piece(peer_request const& p, char const* data); void incoming_piece_fragment(); void incoming_cancel(peer_request const& r); @@ -326,6 +363,8 @@ namespace libtorrent void send_interested(); void send_not_interested(); + void snub_peer(); + // adds a block to the request queue void add_request(piece_block const& b); // removes a block from the request queue or download queue @@ -370,7 +409,8 @@ namespace libtorrent // these functions are virtual to let bt_peer_connection hook into them // and encrypt the content - virtual void send_buffer(char const* begin, int size); + enum message_type_flags { message_type_request = 1 }; + virtual void send_buffer(char const* begin, int size, int flags = 0); virtual buffer::interval allocate_send_buffer(int size); virtual void setup_send(); @@ -400,6 +440,19 @@ namespace libtorrent int send_buffer_capacity() const { return m_send_buffer.capacity(); } + int packet_size() const { return m_packet_size; } + + bool packet_finished() const + { return m_packet_size <= m_recv_pos; } + +#ifndef NDEBUG + bool piece_failed; +#endif + + // upload and download channel state + // enum from peer_info::bw_state + char m_channel_state[2]; + protected: virtual void get_specific_peer_info(peer_info& p) const = 0; @@ -412,7 +465,7 @@ namespace libtorrent virtual void write_cancel(peer_request const& r) = 0; virtual void write_have(int index) = 0; virtual void write_keepalive() = 0; - virtual void write_piece(peer_request const& r, char* buffer) = 0; + virtual void write_piece(peer_request const& r, disk_buffer_holder& buffer) = 0; virtual void write_reject_request(peer_request const& r) = 0; virtual void write_allow_fast(int piece) = 0; @@ -420,18 +473,22 @@ namespace libtorrent virtual void on_connected() = 0; virtual void on_tick() {} - virtual void on_receive(asio::error_code const& error + virtual void on_receive(error_code const& error , std::size_t bytes_transferred) = 0; - virtual void on_sent(asio::error_code const& error + virtual void on_sent(error_code const& error , std::size_t bytes_transferred) = 0; #ifndef TORRENT_DISABLE_ENCRYPTION buffer::interval wr_recv_buffer() { + TORRENT_ASSERT(!m_disk_recv_buffer); + TORRENT_ASSERT(m_disk_recv_buffer_size == 0); if (m_recv_buffer.empty()) return buffer::interval(0,0); return buffer::interval(&m_recv_buffer[0] , &m_recv_buffer[0] + m_recv_pos); } + + std::pair wr_recv_buffers(int bytes); #endif buffer::const_interval receive_buffer() const @@ -441,15 +498,11 @@ namespace libtorrent , &m_recv_buffer[0] + m_recv_pos); } + bool allocate_disk_receive_buffer(int disk_buffer_size); + char* release_disk_receive_buffer(); + bool has_disk_receive_buffer() const { return m_disk_recv_buffer; } void cut_receive_buffer(int size, int packet_size); - void reset_recv_buffer(int packet_size); - int packet_size() const { return m_packet_size; } - - bool packet_finished() const - { - return m_packet_size <= m_recv_pos; - } void setup_receive(); @@ -472,9 +525,9 @@ namespace libtorrent // called from the main loop when this connection has any // work to do. - void on_send_data(asio::error_code const& error + void on_send_data(error_code const& error , std::size_t bytes_transferred); - void on_receive_data(asio::error_code const& error + void on_receive_data(error_code const& error , std::size_t bytes_transferred); // this is the limit on the number of outstanding requests @@ -500,6 +553,14 @@ namespace libtorrent char m_country[2]; #endif +#ifndef NDEBUG + boost::intrusive_ptr self() + { + TORRENT_ASSERT(!m_in_constructor); + return intrusive_ptr_base::self(); + } +#endif + private: void fill_send_buffer(); @@ -507,9 +568,6 @@ namespace libtorrent void on_disk_write_complete(int ret, disk_io_job const& j , peer_request r, boost::shared_ptr t); - // the timeout in seconds - int m_timeout; - // the time when we last got a part of a // piece packet from this peer ptime m_last_piece; @@ -522,21 +580,66 @@ namespace libtorrent // the time when we unchoked this peer ptime m_last_unchoke; - int m_packet_size; - int m_recv_pos; - buffer m_recv_buffer; - - chained_buffer m_send_buffer; - - // the number of bytes we are currently reading - // from disk, that will be added to the send - // buffer as soon as they complete - int m_reading_bytes; - // timeouts ptime m_last_receive; ptime m_last_sent; + // the time when the first entry in the + // request queue was requested, increased + // for each entry that is popped from the + // download queue. Used for request timeout + ptime m_requested; + + // if the timeout is extended for the outstanding + // requests, this is the number of seconds it was + // extended. + int m_timeout_extend; + + // a timestamp when the remote download rate + // was last updated + ptime m_remote_dl_update; + + // the time when async_connect was called + // or when the incoming connection was established + ptime m_connect; + + // the time when this peer sent us a not_interested message + // the last time. + ptime m_became_uninterested; + + // the time when we sent a not_interested message to + // this peer the last time. + ptime m_became_uninteresting; + + // the amount of data this peer has been given + // as free upload. This is distributed from + // peers from which we get free download + // this will be negative on a peer from which + // we get free download, and positive on peers + // that we give the free upload, to keep the balance. + size_type m_free_upload; + + // the total payload download bytes + // at the last unchoke cycle. This is used to + // measure the number of bytes transferred during + // an unchoke cycle, to unchoke peers the more bytes + // they sent us + size_type m_downloaded_at_last_unchoke; + +#ifndef TORRENT_DISABLE_GEO_IP + std::string m_inet_as_name; +#endif + + buffer m_recv_buffer; + + // if this peer is receiving a piece, this + // points to a disk buffer that the data is + // read into. This eliminates a memcopy from + // the receive buffer into the disk buffer + disk_buffer_holder m_disk_recv_buffer; + + chained_buffer m_send_buffer; + boost::shared_ptr m_socket; // this is the peer we're actually talking to // it may not necessarily be the peer we're @@ -549,51 +652,12 @@ namespace libtorrent // until the info_hash is received. Then it's // set to the torrent it belongs to. boost::weak_ptr m_torrent; - // is true if it was we that connected to the peer - // and false if we got an incoming connection - // could be considered: true = local, false = remote - bool m_active; // remote peer's id peer_id m_peer_id; - // other side says that it's interested in downloading - // from us. - bool m_peer_interested; - - // the other side has told us that it won't send anymore - // data to us for a while - bool m_peer_choked; - - // the peer has pieces we are interested in - bool m_interesting; - - // we have choked the upload to the peer - bool m_choked; - - // this is set to true if the connection timed - // out or closed the connection. In that - // case we will not try to reconnect to - // this peer - bool m_failed; - - // if this is set to true, the peer will not - // request bandwidth from the limiter, but instead - // just send and receive as much as possible. - bool m_ignore_bandwidth_limits; - // the pieces the other end have - std::vector m_have_piece; - // this is set to true when a have_all - // message is received. This information - // is used to fill the bitmask in init() - bool m_have_all; - - // the number of pieces this peer - // has. Must be the same as - // std::count(m_have_piece.begin(), - // m_have_piece.end(), true) - int m_num_pieces; + bitfield m_have_piece; // the queue of requests we have got // from this peer @@ -605,27 +669,48 @@ namespace libtorrent // the queue of blocks we have requested // from this peer - std::deque m_download_queue; + std::deque m_download_queue; - // the number of request we should queue up - // at the remote end. - int m_desired_queue_size; + // the pieces we will send to the peer + // if requested (regardless of choke state) + std::set m_accept_fast; - // the amount of data this peer has been given - // as free upload. This is distributed from - // peers from which we get free download - // this will be negative on a peer from which - // we get free download, and positive on peers - // that we give the free upload, to keep the balance. - size_type m_free_upload; + // the pieces the peer will send us if + // requested (regardless of choke state) + std::vector m_allowed_fast; - // if this is true, this peer is assumed to handle all piece - // requests in fifo order. All skipped blocks are re-requested - // immediately instead of having a looser requirement - // where blocks can be sent out of order. The default is to - // allow non-fifo order. - bool m_assume_fifo; + // pieces that has been suggested to be + // downloaded from this peer + std::vector m_suggested_pieces; + // a list of byte offsets inside the send buffer + // the piece requests + std::vector m_requests_in_buffer; + + // the number of pieces this peer + // has. Must be the same as + // std::count(m_have_piece.begin(), + // m_have_piece.end(), true) + int m_num_pieces; + + // the timeout in seconds + int m_timeout; + + // the size (in bytes) of the bittorrent message + // we're currently receiving + int m_packet_size; + + // the number of bytes of the bittorrent payload + // we've received so far + int m_recv_pos; + + int m_disk_recv_buffer_size; + + // the number of bytes we are currently reading + // from disk, that will be added to the send + // buffer as soon as they complete + int m_reading_bytes; + // the number of invalid piece-requests // we have got from this peer. If the request // queue gets empty, and there have been @@ -635,55 +720,6 @@ namespace libtorrent // by sending choke, unchoke. int m_num_invalid_requests; - // this is true if this connection has been added - // to the list of connections that will be closed. - bool m_disconnecting; - - // the time when this peer sent us a not_interested message - // the last time. - ptime m_became_uninterested; - - // the time when we sent a not_interested message to - // this peer the last time. - ptime m_became_uninteresting; - - // this is true until this socket has become - // writable for the first time (i.e. the - // connection completed). While connecting - // the timeout will not be triggered. This is - // because windows XP SP2 may delay connection - // attempts, which means that the connection - // may not even have been attempted when the - // time out is reached. - bool m_connecting; - - // This is true until connect is called on the - // peer_connection's socket. It is false on incoming - // connections. - bool m_queued; - - // these are true when there's a asynchronous write - // or read operation in progress. Or an asyncronous bandwidth - // request is in progress. - bool m_writing; - bool m_reading; - - // if set to non-zero, this peer will always prefer - // to request entire n pieces, rather than blocks. - // where n is the value of this variable. - // if it is 0, the download rate limit setting - // will be used to determine if whole pieces - // are preferred. - int m_prefer_whole_pieces; - - // if this is true, the blocks picked by the piece - // picker will be merged before passed to the - // request function. i.e. subsequent blocks are - // merged into larger blocks. This is used by - // the http-downloader, to request whole pieces - // at a time. - bool m_request_large_blocks; - // this is the priority with which this peer gets // download bandwidth quota assigned to it. int m_priority; @@ -715,36 +751,112 @@ namespace libtorrent // approximate peer download rate int m_remote_dl_rate; - // a timestamp when the remote download rate - // was last updated - ptime m_remote_dl_update; - - // the pieces we will send to the peer - // if requested (regardless of choke state) - std::set m_accept_fast; - - // the pieces the peer will send us if - // requested (regardless of choke state) - std::vector m_allowed_fast; - - // pieces that has been suggested to be - // downloaded from this peer - std::vector m_suggested_pieces; - // the number of bytes send to the disk-io // thread that hasn't yet been completely written. int m_outstanding_writing_bytes; + // max transfer rates seen on this peer + int m_download_rate_peak; + int m_upload_rate_peak; + + // estimated round trip time to this peer + // based on the time from when async_connect + // was called to when on_connection_complete + // was called. The rtt is specified in milliseconds + boost::uint16_t m_rtt; + + // if set to non-zero, this peer will always prefer + // to request entire n pieces, rather than blocks. + // where n is the value of this variable. + // if it is 0, the download rate limit setting + // will be used to determine if whole pieces + // are preferred. + boost::uint8_t m_prefer_whole_pieces; + + // the number of request we should queue up + // at the remote end. + boost::uint8_t m_desired_queue_size; + // if this is true, the disconnection // timestamp is not updated when the connection // is closed. This means the time until we can // reconnect to this peer is shorter, and likely // immediate. - bool m_fast_reconnect; + bool m_fast_reconnect:1; + // is true if it was we that connected to the peer + // and false if we got an incoming connection + // could be considered: true = local, false = remote + bool m_active:1; + + // other side says that it's interested in downloading + // from us. + bool m_peer_interested:1; + + // the other side has told us that it won't send anymore + // data to us for a while + bool m_peer_choked:1; + + // the peer has pieces we are interested in + bool m_interesting:1; + + // we have choked the upload to the peer + bool m_choked:1; + + // this is set to true if the connection timed + // out or closed the connection. In that + // case we will not try to reconnect to + // this peer + bool m_failed:1; + + // if this is set to true, the peer will not + // request bandwidth from the limiter, but instead + // just send and receive as much as possible. + bool m_ignore_bandwidth_limits:1; + + // this is set to true when a have_all + // message is received. This information + // is used to fill the bitmask in init() + bool m_have_all:1; + + // this is true if this connection has been added + // to the list of connections that will be closed. + bool m_disconnecting:1; + + // this is true until this socket has become + // writable for the first time (i.e. the + // connection completed). While connecting + // the timeout will not be triggered. This is + // because windows XP SP2 may delay connection + // attempts, which means that the connection + // may not even have been attempted when the + // time out is reached. + bool m_connecting:1; + + // This is true until connect is called on the + // peer_connection's socket. It is false on incoming + // connections. + bool m_queued:1; + + // if this is true, the blocks picked by the piece + // picker will be merged before passed to the + // request function. i.e. subsequent blocks are + // merged into larger blocks. This is used by + // the http-downloader, to request whole pieces + // at a time. + bool m_request_large_blocks:1; + + // set to true when this peer is only uploading + bool m_upload_only:1; + + // set to true when a piece request times out. The + // result is that the desired pending queue size + // is set to 1 + bool m_snubbed:1; + #ifndef NDEBUG public: - bool m_in_constructor; + bool m_in_constructor:1; #endif }; } diff --git a/libtorrent/include/libtorrent/peer_id.hpp b/libtorrent/include/libtorrent/peer_id.hpp old mode 100755 new mode 100644 index e35775544..0ec096de3 --- a/libtorrent/include/libtorrent/peer_id.hpp +++ b/libtorrent/include/libtorrent/peer_id.hpp @@ -48,8 +48,6 @@ namespace libtorrent class TORRENT_EXPORT big_number { - // private type - struct private_pointer {}; // the number of bytes of the number enum { number_size = 20 }; public: @@ -57,16 +55,19 @@ namespace libtorrent big_number() {} - big_number(std::string const& s) + explicit big_number(char const* s) + { + if (s == 0) clear(); + else std::memcpy(m_number, s, size); + } + + explicit big_number(std::string const& s) { TORRENT_ASSERT(s.size() >= 20); int sl = int(s.size()) < size ? int(s.size()) : size; std::memcpy(m_number, &s[0], sl); } - // when initialized with 0 - big_number(private_pointer*) { clear(); } - void clear() { std::fill(m_number,m_number+number_size,0); diff --git a/libtorrent/include/libtorrent/peer_info.hpp b/libtorrent/include/libtorrent/peer_info.hpp old mode 100755 new mode 100644 index e65f33a18..83aa217cf --- a/libtorrent/include/libtorrent/peer_info.hpp +++ b/libtorrent/include/libtorrent/peer_info.hpp @@ -33,12 +33,11 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef TORRENT_PEER_INFO_HPP_INCLUDED #define TORRENT_PEER_INFO_HPP_INCLUDED -#include - #include "libtorrent/socket.hpp" #include "libtorrent/peer_id.hpp" #include "libtorrent/size_type.hpp" #include "libtorrent/config.hpp" +#include "libtorrent/bitfield.hpp" namespace libtorrent { @@ -57,7 +56,8 @@ namespace libtorrent queued = 0x100, on_parole = 0x200, seed = 0x400, - optimistic_unchoke = 0x800 + optimistic_unchoke = 0x800, + snubbed = 0x1000 #ifndef TORRENT_DISABLE_ENCRYPTION , rc4_encrypted = 0x100000, plaintext_encrypted = 0x200000 @@ -78,6 +78,16 @@ namespace libtorrent int source; + // bw_idle: the channel is not used + // bw_torrent: the channel is waiting for torrent quota + // bw_global: the channel is waiting for global quota + // bw_network: the channel is waiting for an async write + // for read operation to complete + enum bw_state { bw_idle, bw_torrent, bw_global, bw_network }; + + char read_state; + char write_state; + tcp::endpoint ip; float up_speed; float down_speed; @@ -86,7 +96,7 @@ namespace libtorrent size_type total_download; size_type total_upload; peer_id pid; - std::vector pieces; + bitfield pieces; int upload_limit; int download_limit; @@ -96,11 +106,18 @@ namespace libtorrent // time since last download or upload time_duration last_active; + // the number of seconds until the current + // pending request times out + int request_timeout; + // the size of the send buffer for this peer, in bytes int send_buffer_size; // the number bytes that's actually used of the send buffer int used_send_buffer; + int receive_buffer_size; + int used_receive_buffer; + // the number of failed hashes for this peer int num_hashfails; @@ -112,6 +129,12 @@ namespace libtorrent char country[2]; #endif +#ifndef TORRENT_DISABLE_GEO_IP + // atonomous system this peer belongs to + std::string inet_as_name; + int inet_as; +#endif + size_type load_balancing; // this is the number of requests @@ -120,6 +143,10 @@ namespace libtorrent // for yet int download_queue_length; + // the number of request messages + // waiting to be sent inside the send buffer + int requests_in_buffer; + // the number of requests that is // tried to be maintained (this is // typically a function of download speed) @@ -157,8 +184,31 @@ namespace libtorrent // number of bytes this peer has in // the disk write queue int pending_disk_bytes; + + // numbers used for bandwidth limiting + int send_quota; + int receive_quota; + + // estimated rtt to peer, in milliseconds + int rtt; + + // the highest transfer rates seen for this peer + int download_rate_peak; + int upload_rate_peak; }; + struct TORRENT_EXPORT peer_list_entry + { + enum flags_t + { + banned = 1, + }; + + tcp::endpoint ip; + int flags; + boost::uint8_t failcount; + boost::uint8_t source; + }; } #endif // TORRENT_PEER_INFO_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/piece_picker.hpp b/libtorrent/include/libtorrent/piece_picker.hpp old mode 100755 new mode 100644 index ef69c3334..bd0f862b6 --- a/libtorrent/include/libtorrent/piece_picker.hpp +++ b/libtorrent/include/libtorrent/piece_picker.hpp @@ -58,6 +58,7 @@ namespace libtorrent class torrent; class peer_connection; + class bitfield; struct TORRENT_EXPORT piece_block { @@ -128,27 +129,24 @@ namespace libtorrent boost::int16_t requested; }; - piece_picker(int blocks_per_piece - , int total_num_blocks); + piece_picker(); void get_availability(std::vector& avail) const; - void set_sequenced_download_threshold(int sequenced_download_threshold); - - // the vector tells which pieces we already have - // and which we don't have. - void files_checked( - std::vector const& pieces - , std::vector const& unfinished - , std::vector& verify_pieces); + void sequential_download(bool sd); + bool sequential_download() const { return m_sequential_download >= 0; } // increases the peer count for the given piece - // (is used when a HAVE or BITFIELD message is received) + // (is used when a HAVE message is received) void inc_refcount(int index); + void dec_refcount(int index); + // increases the peer count for the given piece + // (is used when a BITFIELD message is received) + void inc_refcount(bitfield const& bitmask); // decreases the peer count for the given piece // (used when a peer disconnects) - void dec_refcount(int index); + void dec_refcount(bitfield const& bitmask); // these will increase and decrease the peer count // of all pieces. They are used when seeds join @@ -161,6 +159,17 @@ namespace libtorrent // we are not interested in this piece anymore // (i.e. we don't have to maintain a refcount) void we_have(int index); + void we_dont_have(int index); + + void init(int blocks_per_piece, int total_num_blocks); + int num_pieces() const { return int(m_piece_map.size()); } + + bool have_piece(int index) const + { + TORRENT_ASSERT(index >= 0); + TORRENT_ASSERT(index < int(m_piece_map.size())); + return m_piece_map[index].index == piece_pos::we_have_index; + } // sets the priority of a piece. // returns true if the priority was changed from 0 to non-0 @@ -191,7 +200,7 @@ namespace libtorrent // THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION! // The last argument is the policy::peer pointer for the peer that // we'll download from. - void pick_pieces(std::vector const& pieces + void pick_pieces(bitfield const& pieces , std::vector& interesting_blocks , int num_pieces, int prefer_whole_pieces , void* peer, piece_state_t speed @@ -205,14 +214,14 @@ namespace libtorrent // blocks to be picked. Blocks are not picked from pieces // that are being downloaded int add_blocks(std::vector const& piece_list - , const std::vector& pieces + , bitfield const& pieces , std::vector& interesting_blocks , int num_blocks, int prefer_whole_pieces , void* peer, std::vector const& ignore) const; // picks blocks only from downloading pieces int add_blocks_downloading( - std::vector const& pieces + bitfield const& pieces , std::vector& interesting_blocks , std::vector& backup_blocks , int num_blocks, int prefer_whole_pieces @@ -237,6 +246,7 @@ namespace libtorrent , piece_state_t s); void mark_as_writing(piece_block block, void* peer); void mark_as_finished(piece_block block, void* peer); + void write_failed(piece_block block); int num_peers(piece_block block) const; // returns information about the given piece @@ -272,11 +282,15 @@ namespace libtorrent // the number of filtered pieces we already have int num_have_filtered() const { return m_num_have_filtered; } + int num_have() const { return m_num_have; } + #ifndef NDEBUG // used in debug mode + void verify_priority(int start, int end, int prio) const; void check_invariant(const torrent* t = 0) const; void verify_pick(std::vector const& picked - , std::vector const& bitfield) const; + , bitfield const& bits) const; + void print_pieces() const; #endif // functor that compares indices on downloading_pieces @@ -295,9 +309,11 @@ namespace libtorrent private: - bool can_pick(int piece, std::vector const& bitmask) const; + friend struct piece_pos; + + bool can_pick(int piece, bitfield const& bitmask) const; std::pair expand_piece(int piece, int whole_pieces - , std::vector const& have) const; + , bitfield const& have) const; struct piece_pos { @@ -342,30 +358,25 @@ namespace libtorrent bool have() const { return index == we_have_index; } void set_have() { index = we_have_index; TORRENT_ASSERT(have()); } + void set_not_have() { index = 0; TORRENT_ASSERT(!have()); } bool filtered() const { return piece_priority == filter_priority; } void filtered(bool f) { piece_priority = f ? filter_priority : 0; } - int priority(int limit) const + int priority(piece_picker const* picker) const { - if (downloading || filtered() || have()) return 0; + if (downloading || filtered() + || have() || peer_count + picker->m_seeds == 0) + return -1; + + // priority 5, 6 and 7 disregards availability of the piece + if (piece_priority > 4) return 7 - piece_priority; + // pieces we are currently downloading have high priority - int prio = peer_count * 2; - // if the peer_count is 0 or 1, the priority cannot be higher - if (prio <= 1) return prio; - if (prio >= limit * 2) prio = limit * 2; - // the different priority levels - switch (piece_priority) - { - case 1: return prio; - case 2: return prio - 1; - case 3: return (std::max)(prio / 2, 1); - case 4: return (std::max)(prio / 2 - 1, 1); - case 5: return (std::max)(prio / 3, 1); - case 6: return (std::max)(prio / 3 - 1, 1); - case 7: return 1; - } - return prio; + int prio = peer_count * 4; +// if (prio >= picker->m_prio_limit * 6) prio = picker->m_prio_limit * 6; + + return prio + (4 - piece_priority); } bool operator!=(piece_pos p) const @@ -378,27 +389,44 @@ namespace libtorrent BOOST_STATIC_ASSERT(sizeof(piece_pos) == sizeof(char) * 4); - bool is_ordered(int priority) const - { - return priority >= m_sequenced_download_threshold * 2; - } + void update_pieces() const; + // fills in the range [start, end) of pieces in + // m_pieces that have priority 'prio' + void priority_range(int prio, int* start, int* end); + + // adds the piece 'index' to m_pieces void add(int index); - void move(int vec_index, int elem_index); + // removes the piece with the given priority and the + // elem_index in the m_pieces vector + void remove(int priority, int elem_index); + // updates the position of the piece with the given + // priority and the elem_index in the m_pieces vector + void update(int priority, int elem_index); + // shuffles the given piece inside it's priority range + void shuffle(int priority, int elem_index); + void sort_piece(std::vector::iterator dp); downloading_piece& add_download_piece(); void erase_download_piece(std::vector::iterator i); - // this vector contains all pieces we don't have. - // in the first entry (index 0) is a vector of all pieces - // that no peer have, the vector at index 1 contains - // all pieces that exactly one peer have, index 2 contains - // all pieces exactly two peers have and so on. - // this is not entirely true. The availibility of a piece - // is adjusted depending on its priority. But the principle - // is that the higher index, the lower priority a piece has. - std::vector > m_piece_info; + // the number of seeds. These are not added to + // the availability counters of the pieces + int m_seeds; + + // the following vectors are mutable because they sometimes may + // be updated lazily, triggered by const functions + + // this vector contains all piece indices that are pickable + // sorted by priority. Pieces are in random random order + // among pieces with the same priority + mutable std::vector m_pieces; + + // these are indices to the priority boundries inside + // the m_pieces vector. priority 0 always start at + // 0, priority 1 starts at m_priority_boundries[0] etc. + mutable std::vector m_priority_boundries; // this maps indices to number of peers that has this piece and // index into the m_piece_info vectors. @@ -406,7 +434,7 @@ namespace libtorrent // doesn't exist in the piece_info buckets // pieces with the filtered flag set doesn't have entries in // the m_piece_info buckets either - std::vector m_piece_map; + mutable std::vector m_piece_map; // each piece that's currently being downloaded // has an entry in this list with block allocations. @@ -438,12 +466,19 @@ namespace libtorrent // the number of pieces we have int m_num_have; - // the required popularity of a piece in order to download - // it in sequence instead of random order. - int m_sequenced_download_threshold; -#ifndef NDEBUG - bool m_files_checked_called; -#endif + // -1 means sequential download is not active. + // >= 0 means that pieces are requested in sequential order + // and this variable is the next piece to request. + // in that case m_pieces is cleared and not used. + int m_sequential_download; + + // if this is set to true, it means update_pieces() + // has to be called before accessing m_pieces. + mutable bool m_dirty; + public: + + enum { max_pieces = piece_pos::we_have_index - 1 }; + }; inline int piece_picker::blocks_in_piece(int index) const diff --git a/libtorrent/include/libtorrent/policy.hpp b/libtorrent/include/libtorrent/policy.hpp old mode 100755 new mode 100644 index 95397b49e..158163531 --- a/libtorrent/include/libtorrent/policy.hpp +++ b/libtorrent/include/libtorrent/policy.hpp @@ -85,24 +85,20 @@ namespace libtorrent // the tracker, pex, lsd or dht. policy::peer* peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid , int source, char flags); - void update_peer_port(int port, policy::peer* p, int src); + + // false means duplicate connection + bool update_peer_port(int port, policy::peer* p, int src); // called when an incoming connection is accepted - void new_connection(peer_connection& c); + // false means the connection was refused or failed + bool new_connection(peer_connection& c); // the given connection was just closed - void connection_closed(const peer_connection& c) throw(); + void connection_closed(const peer_connection& c); // the peer has got at least one interesting piece void peer_is_interesting(peer_connection& c); - void piece_finished(int index, bool successfully_verified); - - // the peer choked us - void choked(peer_connection& c); - - int count_choked() const; - // the peer unchoked us void unchoked(peer_connection& c); @@ -123,56 +119,27 @@ namespace libtorrent struct peer { enum connection_type { not_connectable, connectable }; - peer(tcp::endpoint const& ip, connection_type t, int src); size_type total_download() const; size_type total_upload() const; // the ip/port pair this peer is or was connected on - // if it was a remote (incoming) connection, type is - // set thereafter. If it was a peer we got from the - // tracker, type is set to local_connection. tcp::endpoint ip; - connection_type type; -#ifndef TORRENT_DISABLE_ENCRYPTION - // Hints encryption support of peer. Only effective for - // and when the outgoing encryption policy allows both - // encrypted and non encrypted connections - // (pe_settings::out_enc_policy == enabled). The initial - // state of this flag determines the initial connection - // attempt type (true = encrypted, false = standard). - // This will be toggled everytime either an encrypted or - // non-encrypted handshake fails. - bool pe_support; +#ifndef TORRENT_DISABLE_GEO_IP +#ifndef NDEBUG + // only used in debug mode to assert that + // the first entry in the AS pair keeps the same + boost::uint16_t inet_as_num; +#endif + // The AS this peer belongs to + std::pair* inet_as; #endif - // the number of failed connection attempts this peer has - int failcount; - // the number of times this peer has been - // part of a piece that failed the hash check - int hashfails; - - // this is true if the peer is a seed - bool seed; - - int fast_reconnects; - - // true if this peer currently is unchoked - // because of an optimistic unchoke. - // when the optimistic unchoke is moved to - // another peer, this peer will be choked - // if this is true - bool optimistically_unchoked; - - // the time when this peer was optimistically unchoked - // the last time. - libtorrent::ptime last_optimistically_unchoked; - - // the time when the peer connected to us - // or disconnected if it isn't connected right now - libtorrent::ptime connected; + // the number of failed connection attempts + // this peer has + boost::uint8_t failcount; // for every valid piece we receive where this // peer was one of the participants, we increase @@ -180,15 +147,68 @@ namespace libtorrent // where this peer was a participant, we decrease // this value. If it sinks below a threshold, its // considered a bad peer and will be banned. - int trust_points; + boost::int8_t trust_points; - // if this is true, the peer has previously participated - // in a piece that failed the piece hash check. This will - // put the peer on parole and only request entire pieces. - // if a piece pass that was partially requested from this - // peer it will leave parole mode and continue download + // a bitmap combining the peer_source flags + // from peer_info. + boost::uint8_t source; + + // the number of times this peer has been + // part of a piece that failed the hash check + boost::uint8_t hashfails; + + // type specifies if the connection was incoming + // or outgoing. If we ever saw this peer as connectable + // it will remain as connectable + unsigned type:4; + + // the number of times we have allowed a fast + // reconnect for this peer. + unsigned fast_reconnects:4; + +#ifndef TORRENT_DISABLE_ENCRYPTION + // Hints encryption support of peer. Only effective + // for and when the outgoing encryption policy + // allows both encrypted and non encrypted + // connections (pe_settings::out_enc_policy + // == enabled). The initial state of this flag + // determines the initial connection attempt + // type (true = encrypted, false = standard). + // This will be toggled everytime either an + // encrypted or non-encrypted handshake fails. + bool pe_support:1; +#endif + // true if this peer currently is unchoked + // because of an optimistic unchoke. + // when the optimistic unchoke is moved to + // another peer, this peer will be choked + // if this is true + bool optimistically_unchoked:1; + + // this is true if the peer is a seed + bool seed:1; + + // if this is true, the peer has previously + // participated in a piece that failed the piece + // hash check. This will put the peer on parole + // and only request entire pieces. If a piece pass + // that was partially requested from this peer it + // will leave parole mode and continue download // pieces as normal peers. - bool on_parole; + bool on_parole:1; + + // is set to true if this peer has been banned + bool banned:1; + +#ifndef TORRENT_DISABLE_DHT + // this is set to true when this peer as been + // pinged by the DHT + bool added_to_dht:1; +#endif + + // if the peer is connected now, this + // will refer to a valid peer_connection + peer_connection* connection; // this is the accumulated amount of // uploaded and downloaded data to this @@ -202,16 +222,13 @@ namespace libtorrent size_type prev_amount_upload; size_type prev_amount_download; - // is set to true if this peer has been banned - bool banned; + // the time when this peer was optimistically unchoked + // the last time. + libtorrent::ptime last_optimistically_unchoked; - // a bitmap combining the peer_source flags - // from peer_info. - int source; - - // if the peer is connected now, this - // will refer to a valid peer_connection - peer_connection* connection; + // the time when the peer connected to us + // or disconnected if it isn't connected right now + libtorrent::ptime connected; }; int num_peers() const { return m_peers.size(); } @@ -224,37 +241,50 @@ namespace libtorrent const_iterator end_peer() const { return m_peers.end(); } bool connect_one_peer(); - bool disconnect_one_peer(); + + bool has_peer(policy::peer const* p) const; + + int num_seeds() const { return m_num_seeds; } + int num_connect_candidates() const { return m_num_connect_candidates; } + void recalculate_connect_candidates() + { + if (m_num_connect_candidates == 0) + m_num_connect_candidates = 1; + } + + void erase_peer(iterator i); private: -/* - bool unchoke_one_peer(); - void choke_one_peer(); - iterator find_choke_candidate(); - iterator find_unchoke_candidate(); - // the seed prefix means that the - // function is used while seeding. - bool seed_unchoke_one_peer(); - void seed_choke_one_peer(); - iterator find_seed_choke_candidate(); - iterator find_seed_unchoke_candidate(); -*/ - iterator find_disconnect_candidate(); + bool compare_peer(policy::peer const& lhs, policy::peer const& rhs + , address const& external_ip) const; + iterator find_connect_candidate(); + bool is_connect_candidate(peer const& p, bool finished); + std::multimap m_peers; + // since the peer list can grow too large + // to scan all of it, start at this iterator + iterator m_round_robin; + torrent* m_torrent; // free download we have got that hasn't // been distributed yet. size_type m_available_free_upload; - // if there is a connection limit, - // we disconnect one peer every minute in hope of - // establishing a connection with a better peer -// ptime m_last_optimistic_disconnect; + // The number of peers in our peer list + // that are connect candidates. i.e. they're + // not already connected and they have not + // yet reached their max try count and they + // have the connectable state (we have a listen + // port for them). + int m_num_connect_candidates; + + // the number of seeds in the peer list + int m_num_seeds; }; } diff --git a/libtorrent/include/libtorrent/proxy_base.hpp b/libtorrent/include/libtorrent/proxy_base.hpp index 037a1c2d4..873e84190 100644 --- a/libtorrent/include/libtorrent/proxy_base.hpp +++ b/libtorrent/include/libtorrent/proxy_base.hpp @@ -38,9 +38,13 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#if BOOST_VERSION < 103500 #include #include - +#else +#include +#include +#endif namespace libtorrent { @@ -52,7 +56,7 @@ public: typedef stream_socket::endpoint_type endpoint_type; typedef stream_socket::protocol_type protocol_type; - explicit proxy_base(asio::io_service& io_service) + explicit proxy_base(io_service& io_service) : m_sock(io_service) , m_resolver(io_service) {} @@ -70,11 +74,12 @@ public: } template - std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec) + std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec) { return m_sock.read_some(buffers, ec); } +#ifndef BOOST_NO_EXCEPTIONS template std::size_t read_some(Mutable_Buffers const& buffers) { @@ -86,9 +91,10 @@ public: { m_sock.io_control(ioc); } +#endif template - void io_control(IO_Control_Command& ioc, asio::error_code& ec) + void io_control(IO_Control_Command& ioc, error_code& ec) { m_sock.io_control(ioc, ec); } @@ -99,68 +105,94 @@ public: m_sock.async_write_some(buffers, handler); } +#ifndef BOOST_NO_EXCEPTIONS + template + void set_option(SettableSocketOption const& opt) + { + m_sock.set_option(opt); + } +#endif + + template + error_code set_option(SettableSocketOption const& opt, error_code& ec) + { + return m_sock.set_option(opt, ec); + } + +#ifndef BOOST_NO_EXCEPTIONS void bind(endpoint_type const& endpoint) { m_sock.bind(endpoint); } +#endif - void bind(endpoint_type const& endpoint, asio::error_code& ec) + void bind(endpoint_type const& endpoint, error_code& ec) { m_sock.bind(endpoint, ec); } +#ifndef BOOST_NO_EXCEPTIONS void open(protocol_type const& p) { m_sock.open(p); } +#endif - void open(protocol_type const& p, asio::error_code& ec) + void open(protocol_type const& p, error_code& ec) { m_sock.open(p, ec); } +#ifndef BOOST_NO_EXCEPTIONS void close() { m_remote_endpoint = endpoint_type(); m_sock.close(); m_resolver.cancel(); } +#endif - void close(asio::error_code& ec) + void close(error_code& ec) { m_sock.close(ec); m_resolver.cancel(); } - endpoint_type remote_endpoint() +#ifndef BOOST_NO_EXCEPTIONS + endpoint_type remote_endpoint() const + { + return m_remote_endpoint; + } +#endif + + endpoint_type remote_endpoint(error_code& ec) const { return m_remote_endpoint; } - endpoint_type remote_endpoint(asio::error_code& ec) - { - return m_remote_endpoint; - } - - endpoint_type local_endpoint() +#ifndef BOOST_NO_EXCEPTIONS + endpoint_type local_endpoint() const { return m_sock.local_endpoint(); } +#endif - endpoint_type local_endpoint(asio::error_code& ec) + endpoint_type local_endpoint(error_code& ec) const { return m_sock.local_endpoint(ec); } - asio::io_service& io_service() + io_service& get_io_service() { - return m_sock.io_service(); + return m_sock.get_io_service(); } lowest_layer_type& lowest_layer() { return m_sock.lowest_layer(); } + + bool is_open() const { return m_sock.is_open(); } protected: diff --git a/libtorrent/include/libtorrent/session.hpp b/libtorrent/include/libtorrent/session.hpp old mode 100755 new mode 100644 index d2ab6ab2e..6b628bdbf --- a/libtorrent/include/libtorrent/session.hpp +++ b/libtorrent/include/libtorrent/session.hpp @@ -61,6 +61,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/version.hpp" #include "libtorrent/fingerprint.hpp" #include "libtorrent/time.hpp" +#include "libtorrent/disk_io_thread.hpp" +#include "libtorrent/peer_id.hpp" #include "libtorrent/storage.hpp" @@ -75,6 +77,8 @@ namespace libtorrent class ip_filter; class port_filter; class connection_queue; + class natpmp; + class upnp; namespace fs = boost::filesystem; @@ -117,13 +121,41 @@ namespace libtorrent boost::shared_ptr m_impl; }; + struct add_torrent_params + { + add_torrent_params(storage_constructor_type sc = default_storage_constructor) + : tracker_url(0) + , name(0) + , resume_data(0) + , storage_mode(storage_mode_sparse) + , paused(true) + , auto_managed(true) + , duplicate_is_error(false) + , storage(sc) + , userdata(0) + {} + + boost::intrusive_ptr ti; + char const* tracker_url; + sha1_hash info_hash; + char const* name; + fs::path save_path; + std::vector* resume_data; + storage_mode_t storage_mode; + bool paused; + bool auto_managed; + bool duplicate_is_error; + storage_constructor_type storage; + void* userdata; + }; + class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_initializer { public: session(fingerprint const& print = fingerprint("LT" , LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0) -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , fs::path logpath = "." #endif ); @@ -131,7 +163,7 @@ namespace libtorrent fingerprint const& print , std::pair listen_port_range , char const* listen_interface = "0.0.0.0" -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , fs::path logpath = "." #endif ); @@ -145,6 +177,9 @@ namespace libtorrent torrent_handle find_torrent(sha1_hash const& info_hash) const; // all torrent_handles must be destructed before the session is destructed! + torrent_handle add_torrent(add_torrent_params const& params); + + // deprecated in 0.14 torrent_handle add_torrent( torrent_info const& ti , fs::path const& save_path @@ -153,6 +188,7 @@ namespace libtorrent , bool paused = false , storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED; + // deprecated in 0.14 torrent_handle add_torrent( boost::intrusive_ptr ti , fs::path const& save_path @@ -160,8 +196,9 @@ namespace libtorrent , storage_mode_t storage_mode = storage_mode_sparse , bool paused = false , storage_constructor_type sc = default_storage_constructor - , void* userdata = 0); + , void* userdata = 0) TORRENT_DEPRECATED; + // deprecated in 0.14 torrent_handle add_torrent( char const* tracker_url , sha1_hash const& info_hash @@ -171,11 +208,19 @@ namespace libtorrent , storage_mode_t storage_mode = storage_mode_sparse , bool paused = false , storage_constructor_type sc = default_storage_constructor - , void* userdata = 0); + , void* userdata = 0) TORRENT_DEPRECATED; session_proxy abort() { return session_proxy(m_impl); } + void pause(); + void resume(); + bool is_paused() const; + session_status status() const; + cache_status get_cache_status() const; + + void get_cache_info(sha1_hash const& ih + , std::vector& ret) const; #ifndef TORRENT_DISABLE_DHT void start_dht(entry const& startup_state = entry()); @@ -195,6 +240,15 @@ namespace libtorrent void add_extension(boost::function(torrent*, void*)> ext); #endif +#ifndef TORRENT_DISABLE_GEO_IP + int as_for_ip(address const& addr); + bool load_asnum_db(char const* file); + bool load_country_db(char const* file); +#endif + + void load_state(entry const& ses_state); + entry state() const; + void set_ip_filter(ip_filter const& f); void set_port_filter(port_filter const& f); void set_peer_id(peer_id const& pid); @@ -263,7 +317,8 @@ namespace libtorrent void set_max_half_open_connections(int limit); std::auto_ptr pop_alert(); - void set_severity_level(alert::severity_t s); + void set_severity_level(alert::severity_t s) TORRENT_DEPRECATED; + void set_alert_mask(int m); alert const* wait_for_alert(time_duration max_wait); @@ -272,8 +327,8 @@ namespace libtorrent // starts/stops UPnP, NATPMP or LSD port mappers // they are stopped by default void start_lsd(); - void start_natpmp(); - void start_upnp(); + natpmp* start_natpmp(); + upnp* start_upnp(); void stop_lsd(); void stop_natpmp(); diff --git a/libtorrent/include/libtorrent/session_impl.hpp b/libtorrent/include/libtorrent/session_impl.hpp deleted file mode 100644 index 67c3fef1d..000000000 --- a/libtorrent/include/libtorrent/session_impl.hpp +++ /dev/null @@ -1,594 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -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. - -*/ - -#ifndef TORRENT_SESSION_IMPL_HPP_INCLUDED -#define TORRENT_SESSION_IMPL_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/policy.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/peer_info.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/fingerprint.hpp" -#include "libtorrent/debug.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/piece_block_progress.hpp" -#include "libtorrent/ip_filter.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/kademlia/dht_tracker.hpp" -#include "libtorrent/session_status.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/stat.hpp" -#include "libtorrent/file_pool.hpp" -#include "libtorrent/bandwidth_manager.hpp" -#include "libtorrent/natpmp.hpp" -#include "libtorrent/upnp.hpp" -#include "libtorrent/lsd.hpp" -#include "libtorrent/socket_type.hpp" -#include "libtorrent/connection_queue.hpp" -#include "libtorrent/disk_io_thread.hpp" - -namespace libtorrent -{ - - namespace fs = boost::filesystem; - - namespace aux - { - struct session_impl; - - // this data is shared between the main thread and the - // thread that initialize pieces - struct piece_checker_data - { - piece_checker_data() - : processing(false), progress(0.f), abort(false) {} - - boost::shared_ptr torrent_ptr; - fs::path save_path; - - sha1_hash info_hash; - - void parse_resume_data( - const entry& rd - , const torrent_info& info - , std::string& error); - - std::vector piece_map; - std::vector unfinished_pieces; - std::vector block_info; - std::vector peers; - entry resume_data; - - // this is true if this torrent is being processed (checked) - // if it is not being processed, then it can be removed from - // the queue without problems, otherwise the abort flag has - // to be set. - bool processing; - - // is filled in by storage::initialize_pieces() - // and represents the progress. It should be a - // value in the range [0, 1] - float progress; - - // abort defaults to false and is typically - // filled in by torrent_handle when the user - // aborts the torrent - bool abort; - }; - - struct checker_impl: boost::noncopyable - { - checker_impl(session_impl& s): m_ses(s), m_abort(false) {} - void operator()(); - piece_checker_data* find_torrent(const sha1_hash& info_hash); - void remove_torrent(sha1_hash const& info_hash); - -#ifndef NDEBUG - void check_invariant() const; -#endif - - // when the files has been checked - // the torrent is added to the session - session_impl& m_ses; - - mutable boost::mutex m_mutex; - boost::condition m_cond; - - // a list of all torrents that are currently in queue - // or checking their files - std::deque > m_torrents; - std::deque > m_processing; - - bool m_abort; - }; - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - struct tracker_logger; -#endif - - // this is the link between the main thread and the - // thread started to run the main downloader loop - struct session_impl: boost::noncopyable - { -#ifndef NDEBUG - friend class ::libtorrent::peer_connection; -#endif - friend struct checker_impl; - friend class invariant_access; - typedef std::map - , boost::intrusive_ptr > - connection_map; - typedef std::map > torrent_map; - - session_impl( - std::pair listen_port_range - , fingerprint const& cl_fprint - , char const* listen_interface = "0.0.0.0"); - ~session_impl(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::function(torrent*)> ext); -#endif - void operator()(); - - void open_listen_port(); - - void async_accept(); - void on_incoming_connection(boost::shared_ptr const& s - , boost::weak_ptr const& as, asio::error_code const& e); - - // must be locked to access the data - // in this struct - typedef boost::recursive_mutex mutex_t; - mutable mutex_t m_mutex; - - boost::weak_ptr find_torrent(const sha1_hash& info_hash); - peer_id const& get_peer_id() const { return m_peer_id; } - - void close_connection(boost::intrusive_ptr const& p); - void connection_failed(boost::shared_ptr const& s - , tcp::endpoint const& a, char const* message); - - void set_settings(session_settings const& s); - session_settings const& settings() const { return m_settings; } - -#ifndef TORRENT_DISABLE_DHT - void add_dht_node(std::pair const& node); - void add_dht_node(udp::endpoint n); - void add_dht_router(std::pair const& node); - void set_dht_settings(dht_settings const& s); - dht_settings const& get_dht_settings() const { return m_dht_settings; } - void start_dht(entry const& startup_state); - void stop_dht(); - entry dht_state() const; -#endif - -#ifndef TORRENT_DISABLE_ENCRYPTION - void set_pe_settings(pe_settings const& settings); - pe_settings const& get_pe_settings() const { return m_pe_settings; } -#endif - - // called when a port mapping is successful, or a router returns - // a failure to map a port - void on_port_mapping(int tcp_port, int udp_port, std::string const& errmsg); - - bool is_aborted() const { return m_abort; } - - void set_ip_filter(ip_filter const& f); - void set_port_filter(port_filter const& f); - - bool listen_on( - std::pair const& port_range - , const char* net_interface = 0); - bool is_listening() const; - - torrent_handle add_torrent( - torrent_info const& ti - , fs::path const& save_path - , entry const& resume_data - , bool compact_mode - , int block_size - , storage_constructor_type sc); - - torrent_handle add_torrent( - char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , fs::path const& save_path - , entry const& resume_data - , bool compact_mode - , int block_size - , storage_constructor_type sc); - - void remove_torrent(torrent_handle const& h); - - std::vector get_torrents(); - - void set_severity_level(alert::severity_t s); - std::auto_ptr pop_alert(); - - int upload_rate_limit() const; - int download_rate_limit() const; - - void set_download_rate_limit(int bytes_per_second); - void set_upload_rate_limit(int bytes_per_second); - void set_max_half_open_connections(int limit); - void set_max_connections(int limit); - void set_max_uploads(int limit); - - int max_connections() const { return m_max_connections; } - int max_uploads() const { return m_max_uploads; } - - int num_uploads() const { return m_num_unchoked; } - int num_connections() const - { return m_connections.size(); } - - void unchoke_peer(peer_connection& c) - { - c.send_unchoke(); - ++m_num_unchoked; - } - - session_status status() const; - void set_peer_id(peer_id const& id); - void set_key(int key); - unsigned short listen_port() const; - - void abort(); - - torrent_handle find_torrent_handle(sha1_hash const& info_hash); - - void announce_lsd(sha1_hash const& ih); - - void set_peer_proxy(proxy_settings const& s) - { m_peer_proxy = s; } - void set_web_seed_proxy(proxy_settings const& s) - { m_web_seed_proxy = s; } - void set_tracker_proxy(proxy_settings const& s) - { m_tracker_proxy = s; } - - proxy_settings const& peer_proxy() const - { return m_peer_proxy; } - proxy_settings const& web_seed_proxy() const - { return m_web_seed_proxy; } - proxy_settings const& tracker_proxy() const - { return m_tracker_proxy; } - -#ifndef TORRENT_DISABLE_DHT - void set_dht_proxy(proxy_settings const& s) - { m_dht_proxy = s; } - proxy_settings const& dht_proxy() const - { return m_dht_proxy; } -#endif - - void start_lsd(); - void start_natpmp(); - void start_upnp(); - - void stop_lsd(); - void stop_natpmp(); - void stop_upnp(); - - // handles delayed alerts - alert_manager m_alerts; - -// private: - - void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih); - - // this is where all active sockets are stored. - // the selector can sleep while there's no activity on - // them - io_service m_io_service; - asio::strand m_strand; - - // the file pool that all storages in this session's - // torrents uses. It sets a limit on the number of - // open files by this session. - // file pool must be destructed after the torrents - // since they will still have references to it - // when they are destructed. - file_pool m_files; - - // handles disk io requests asynchronously - disk_io_thread m_disk_thread; - - // this is a list of half-open tcp connections - // (only outgoing connections) - // this has to be one of the last - // members to be destructed - connection_queue m_half_open; - - // the bandwidth manager is responsible for - // handing out bandwidth to connections that - // asks for it, it can also throttle the - // rate. - bandwidth_manager m_download_channel; - bandwidth_manager m_upload_channel; - - bandwidth_manager* m_bandwidth_manager[2]; - - tracker_manager m_tracker_manager; - torrent_map m_torrents; - - // this maps sockets to their peer_connection - // object. It is the complete list of all connected - // peers. - connection_map m_connections; - - // filters incoming connections - ip_filter m_ip_filter; - - // filters outgoing connections - port_filter m_port_filter; - - // the peer id that is generated at the start of the session - peer_id m_peer_id; - - // the key is an id that is used to identify the - // client with the tracker only. It is randomized - // at startup - int m_key; - - // the range of ports we try to listen on - std::pair m_listen_port_range; - - // the ip-address of the interface - // we are supposed to listen on. - // if the ip is set to zero, it means - // that we should let the os decide which - // interface to listen on - tcp::endpoint m_listen_interface; - - // this is typically set to the same as the local - // listen port. In case a NAT port forward was - // successfully opened, this will be set to the - // port that is open on the external (NAT) interface - // on the NAT box itself. This is the port that has - // to be published to peers, since this is the port - // the client is reachable through. - int m_external_listen_port; - - boost::shared_ptr m_listen_socket; - - // the settings for the client - session_settings m_settings; - // the proxy settings for different - // kinds of connections - proxy_settings m_peer_proxy; - proxy_settings m_web_seed_proxy; - proxy_settings m_tracker_proxy; -#ifndef TORRENT_DISABLE_DHT - proxy_settings m_dht_proxy; -#endif - - // set to true when the session object - // is being destructed and the thread - // should exit - volatile bool m_abort; - - int m_max_uploads; - int m_max_connections; - - // the number of unchoked peers - int m_num_unchoked; - - // this is initialized to the unchoke_interval - // session_setting and decreased every second. - // when it reaches zero, it is reset to the - // unchoke_interval and the unchoke set is - // recomputed. - int m_unchoke_time_scaler; - - // works like unchoke_time_scaler but it - // is only decresed when the unchoke set - // is recomputed, and when it reaches zero, - // the optimistic unchoke is moved to another peer. - int m_optimistic_unchoke_time_scaler; - - // works like unchoke_time_scaler. Each time - // it reaches 0, and all the connections are - // used, the worst connection will be disconnected - // from the torrent with the most peers - int m_disconnect_time_scaler; - - // statistics gathered from all torrents. - stat m_stat; - - // is false by default and set to true when - // the first incoming connection is established - // this is used to know if the client is behind - // NAT or not. - bool m_incoming_connection; - - void second_tick(asio::error_code const& e); - ptime m_last_tick; - -#ifndef TORRENT_DISABLE_DHT - boost::intrusive_ptr m_dht; - dht_settings m_dht_settings; - // if this is set to true, the dht listen port - // will be set to the same as the tcp listen port - // and will be synchronlized with it as it changes - // it defaults to true - bool m_dht_same_port; - - // see m_external_listen_port. This is the same - // but for the udp port used by the DHT. - int m_external_udp_port; -#endif - -#ifndef TORRENT_DISABLE_ENCRYPTION - pe_settings m_pe_settings; -#endif - - boost::shared_ptr m_natpmp; - boost::shared_ptr m_upnp; - boost::shared_ptr m_lsd; - - // the timer used to fire the second_tick - deadline_timer m_timer; - - // the index of the torrent that will be offered to - // connect to a peer next time second_tick is called. - // This implements a round robin. - int m_next_connect_torrent; -#ifndef NDEBUG - void check_invariant(const char *place = 0); -#endif - -#ifdef TORRENT_STATS - // logger used to write bandwidth usage statistics - std::ofstream m_stats_logger; - int m_second_counter; -#endif -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - boost::shared_ptr create_log(std::string const& name - , int instance, bool append = true); - - // this list of tracker loggers serves as tracker_callbacks when - // shutting down. This list is just here to keep them alive during - // whe shutting down process - std::list > m_tracker_loggers; - - public: - boost::shared_ptr m_logger; - private: -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - typedef std::list(torrent*)> > extension_list_t; - - extension_list_t m_extensions; -#endif - - // data shared between the main thread - // and the checker thread - checker_impl m_checker_impl; - - // the main working thread - boost::scoped_ptr m_thread; - - // the thread that calls initialize_pieces() - // on all torrents before they start downloading - boost::scoped_ptr m_checker_thread; - }; - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - struct tracker_logger : request_callback - { - tracker_logger(session_impl& ses): m_ses(ses) {} - void tracker_warning(std::string const& str) - { - debug_log("*** tracker warning: " + str); - } - - void tracker_response(tracker_request const& - , std::vector& peers - , int interval - , int complete - , int incomplete) - { - std::stringstream s; - s << "TRACKER RESPONSE:\n" - "interval: " << interval << "\n" - "peers:\n"; - for (std::vector::const_iterator i = peers.begin(); - i != peers.end(); ++i) - { - s << " " << std::setfill(' ') << std::setw(16) << i->ip - << " " << std::setw(5) << std::dec << i->port << " "; - if (!i->pid.is_all_zeros()) s << " " << i->pid; - s << "\n"; - } - debug_log(s.str()); - } - - void tracker_request_timed_out( - tracker_request const&) - { - debug_log("*** tracker timed out"); - } - - void tracker_request_error( - tracker_request const& - , int response_code - , const std::string& str) - { - debug_log(std::string("*** tracker error: ") - + boost::lexical_cast(response_code) + ": " - + str); - } - - void debug_log(const std::string& line) - { - (*m_ses.m_logger) << line << "\n"; - } - session_impl& m_ses; - }; -#endif - - } -} - - -#endif - diff --git a/libtorrent/include/libtorrent/session_settings.hpp b/libtorrent/include/libtorrent/session_settings.hpp index 2817d27d2..c7aee4a0f 100644 --- a/libtorrent/include/libtorrent/session_settings.hpp +++ b/libtorrent/include/libtorrent/session_settings.hpp @@ -88,6 +88,7 @@ namespace libtorrent , stop_tracker_timeout(5) , tracker_maximum_response_length(1024*1024) , piece_timeout(10) + , request_timeout(40) , request_queue_time(3.f) , max_allowed_in_request_queue(250) , max_out_request_queue(200) @@ -118,6 +119,26 @@ namespace libtorrent #endif , free_torrent_hashes(true) , upnp_ignore_nonrouters(true) + , send_buffer_watermark(80 * 1024) + , auto_upload_slots(true) + , cache_size(512) + , cache_expiry(60) + , outgoing_ports(0,0) + , peer_tos(0) + , active_downloads(8) + , active_seeds(5) + , active_limit(15) + , dont_count_slow_torrents(true) + , auto_manage_interval(30) + , share_ratio_limit(2.f) + , seed_time_ratio_limit(7.f) + , seed_time_limit(24 * 60 * 60) // 24 hours + , peer_turnover(1 / 50.f) + , peer_turnover_cutoff(1.f) + , close_redundant_connections(true) + , auto_scrape_interval(1800) + , auto_scrape_min_interval(300) + , max_peerlist_size(8000) {} // this is the user agent that will be sent to the tracker @@ -148,6 +169,11 @@ namespace libtorrent // it times out if no piece response is returned. int piece_timeout; + // the number of seconds one block (16kB) is expected + // to be received within. If it's not, the block is + // requested from a different peer + int request_timeout; + // the length of the request queue given in the number // of seconds it should take for the other end to send // all the pieces. i.e. the actual number of requests @@ -298,8 +324,106 @@ namespace libtorrent // any upnp devices that don't have an address that matches // our currently configured router. bool upnp_ignore_nonrouters; - }; + + // if the send buffer has fewer bytes than this, we'll + // read another 16kB block onto it. If set too small, + // upload rate capacity will suffer. If set too high, + // memory will be wasted. + // The actual watermark may be lower than this in case + // the upload rate is low, this is the upper limit. + int send_buffer_watermark; + + // if auto_upload_slots is true, and a global upload + // limit is set and the upload rate is less than 90% + // of the upload limit, on new slot is opened up. If + // the upload rate is >= upload limit for an extended + // period of time, one upload slot is closed. The + // upload slots are never automatically decreased below + // the manual settings, through max_uploads. + bool auto_upload_slots; + + // the disk write cache, specified in 16 KiB blocks. + // default is 512 (= 8 MB) + int cache_size; + + // the number of seconds a write cache entry sits + // idle in the cache before it's forcefully flushed + // to disk. Default is 60 seconds. + int cache_expiry; + + // if != (0, 0), this is the range of ports that + // outgoing connections will be bound to. This + // is useful for users that have routers that + // allow QoS settings based on local port. + std::pair outgoing_ports; + + // the TOS byte of all peer traffic (including + // web seeds) is set to this value. The default + // is the QBSS scavenger service + // http://qbone.internet2.edu/qbss/ + // For unmarked packets, set to 0 + char peer_tos; + + // for auto managed torrents, these are the limits + // they are subject to. If there are too many torrents + // some of the auto managed ones will be paused until + // some slots free up. + int active_downloads; + int active_seeds; + int active_limit; + + // if this is true, torrents that don't have any significant + // transfers are not counted as active when determining which + // auto managed torrents to pause and resume + bool dont_count_slow_torrents; + + // the number of seconds in between recalculating which + // torrents to activate and which ones to queue + int auto_manage_interval; + // when a seeding torrent reaches eaither the share ratio + // (bytes up / bytes down) or the seed time ratio + // (seconds as seed / seconds as downloader) or the seed + // time limit (seconds as seed) it is considered + // done, and it will leave room for other torrents + // the default value for share ratio is 2 + // the default seed time ratio is 7, because that's a common + // asymmetry ratio on connections + float share_ratio_limit; + float seed_time_ratio_limit; + int seed_time_limit; + + // the percentage of peers to disconnect every + // 90 seconds (if we're at the peer limit) + // defaults to 1/50:th + float peer_turnover; + + // when we are connected to more than + // limit * peer_turnover_enable peers + // disconnect peer_turnover fraction + // of the peers + float peer_turnover_cutoff; + + // if this is true (default) connections where both + // ends have no utility in keeping the connection open + // are closed. for instance if both ends have completed + // their downloads + bool close_redundant_connections; + + // the number of seconds between scrapes of + // queued torrents (auto managed and paused) + int auto_scrape_interval; + + // the minimum number of seconds between any + // automatic scrape (regardless of torrent) + int auto_scrape_min_interval; + + // the max number of peers in the peer list + // per torrent. This is the peers we know + // about, not necessarily connected to. + int max_peerlist_size; + }; + #ifndef TORRENT_DISABLE_DHT struct dht_settings { diff --git a/libtorrent/include/libtorrent/session_status.hpp b/libtorrent/include/libtorrent/session_status.hpp index e0a9b88a7..4e42dba5f 100644 --- a/libtorrent/include/libtorrent/session_status.hpp +++ b/libtorrent/include/libtorrent/session_status.hpp @@ -54,6 +54,8 @@ namespace libtorrent size_type total_payload_upload; int num_peers; + int num_unchoked; + int allowed_upload_slots; int up_bandwidth_queue; int down_bandwidth_queue; diff --git a/libtorrent/include/libtorrent/size_type.hpp b/libtorrent/include/libtorrent/size_type.hpp old mode 100755 new mode 100644 diff --git a/libtorrent/include/libtorrent/socket.hpp b/libtorrent/include/libtorrent/socket.hpp old mode 100755 new mode 100644 index 90d15e73d..d041024bb --- a/libtorrent/include/libtorrent/socket.hpp +++ b/libtorrent/include/libtorrent/socket.hpp @@ -45,14 +45,27 @@ POSSIBILITY OF SUCH DAMAGE. #define Protocol Protocol_ #endif +#include + +#if BOOST_VERSION < 103500 #include #include #include #include #include -#include +#include #include #include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif #ifdef __OBJC__ #undef Protocol @@ -68,24 +81,12 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { -/* - namespace asio = boost::asio; - - using boost::asio::ipv4::tcp; - using boost::asio::ipv4::address; - using boost::asio::stream_socket; - using boost::asio::datagram_socket; - using boost::asio::socket_acceptor; - using boost::asio::io_service; - using boost::asio::ipv4::host_resolver; - using boost::asio::async_write; - using boost::asio::ipv4::host; - using boost::asio::deadline_timer; -*/ -// namespace asio = ::asio; - +#if BOOST_VERSION < 103500 using asio::ip::tcp; using asio::ip::udp; + using asio::async_write; + using asio::async_read; + typedef asio::ip::tcp::socket stream_socket; typedef asio::ip::address address; typedef asio::ip::address_v4 address_v4; @@ -93,16 +94,42 @@ namespace libtorrent typedef asio::ip::udp::socket datagram_socket; typedef asio::ip::tcp::acceptor socket_acceptor; typedef asio::io_service io_service; + typedef asio::error_code error_code; - using asio::async_write; - using asio::error_code; - + namespace asio = ::asio; typedef asio::basic_deadline_timer deadline_timer; +#else + using boost::system::error_code; + using boost::asio::ip::tcp; + using boost::asio::ip::udp; + using boost::asio::async_write; + using boost::asio::async_read; + + typedef boost::asio::ip::tcp::socket stream_socket; + typedef boost::asio::ip::address address; + typedef boost::asio::ip::address_v4 address_v4; + typedef boost::asio::ip::address_v6 address_v6; + typedef boost::asio::ip::udp::socket datagram_socket; + typedef boost::asio::ip::tcp::acceptor socket_acceptor; + typedef boost::asio::io_service io_service; + + namespace asio = boost::asio; + typedef boost::asio::basic_deadline_timer deadline_timer; +#endif + inline std::ostream& print_address(std::ostream& os, address const& addr) + { + error_code ec; + std::string a = addr.to_string(ec); + if (ec) return os; + os << a; + return os; + } + inline std::ostream& print_endpoint(std::ostream& os, tcp::endpoint const& ep) { address const& addr = ep.address(); - asio::error_code ec; + error_code ec; std::string a = addr.to_string(ec); if (ec) return os; @@ -125,7 +152,7 @@ namespace libtorrent } else if (a.is_v6()) { - asio::ip::address_v6::bytes_type bytes + address_v6::bytes_type bytes = a.to_v6().to_bytes(); std::copy(bytes.begin(), bytes.end(), out); } @@ -135,18 +162,18 @@ namespace libtorrent address read_v4_address(InIt& in) { unsigned long ip = read_uint32(in); - return asio::ip::address_v4(ip); + return address_v4(ip); } template address read_v6_address(InIt& in) { - typedef asio::ip::address_v6::bytes_type bytes_t; + typedef address_v6::bytes_type bytes_t; bytes_t bytes; for (bytes_t::iterator i = bytes.begin() , end(bytes.end()); i != end; ++i) *i = read_uint8(in); - return asio::ip::address_v6(bytes); + return address_v6(bytes); } template @@ -187,6 +214,19 @@ namespace libtorrent int m_value; }; + struct type_of_service + { + type_of_service(char val): m_value(val) {} + template + int level(Protocol const&) const { return IPPROTO_IP; } + template + int name(Protocol const&) const { return IP_TOS; } + template + char const* data(Protocol const&) const { return &m_value; } + template + size_t size(Protocol const&) const { return sizeof(m_value); } + char m_value; + }; } #endif // TORRENT_SOCKET_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/socks4_stream.hpp b/libtorrent/include/libtorrent/socks4_stream.hpp index 9530f9d57..e7054595e 100644 --- a/libtorrent/include/libtorrent/socks4_stream.hpp +++ b/libtorrent/include/libtorrent/socks4_stream.hpp @@ -41,8 +41,8 @@ class socks4_stream : public proxy_base { public: - explicit socks4_stream(asio::io_service& io_service) - : proxy_base(io_service) + explicit socks4_stream(io_service& io_service_) + : proxy_base(io_service_) {} void set_username(std::string const& user) @@ -50,7 +50,7 @@ public: m_user = user; } - typedef boost::function handler_type; + typedef boost::function handler_type; template void async_connect(endpoint_type const& endpoint, Handler const& handler) @@ -74,11 +74,11 @@ public: private: - void name_lookup(asio::error_code const& e, tcp::resolver::iterator i + void name_lookup(error_code const& e, tcp::resolver::iterator i , boost::shared_ptr h); - void connected(asio::error_code const& e, boost::shared_ptr h); - void handshake1(asio::error_code const& e, boost::shared_ptr h); - void handshake2(asio::error_code const& e, boost::shared_ptr h); + void connected(error_code const& e, boost::shared_ptr h); + void handshake1(error_code const& e, boost::shared_ptr h); + void handshake2(error_code const& e, boost::shared_ptr h); // send and receive buffer std::vector m_buffer; diff --git a/libtorrent/include/libtorrent/socks5_stream.hpp b/libtorrent/include/libtorrent/socks5_stream.hpp index 622557cd2..24b27da85 100644 --- a/libtorrent/include/libtorrent/socks5_stream.hpp +++ b/libtorrent/include/libtorrent/socks5_stream.hpp @@ -41,7 +41,7 @@ class socks5_stream : public proxy_base { public: - explicit socks5_stream(asio::io_service& io_service) + explicit socks5_stream(io_service& io_service) : proxy_base(io_service) {} @@ -52,7 +52,7 @@ public: m_password = password; } - typedef boost::function handler_type; + typedef boost::function handler_type; template void async_connect(endpoint_type const& endpoint, Handler const& handler) @@ -79,17 +79,17 @@ public: private: - void name_lookup(asio::error_code const& e, tcp::resolver::iterator i + void name_lookup(error_code const& e, tcp::resolver::iterator i , boost::shared_ptr h); - void connected(asio::error_code const& e, boost::shared_ptr h); - void handshake1(asio::error_code const& e, boost::shared_ptr h); - void handshake2(asio::error_code const& e, boost::shared_ptr h); - void handshake3(asio::error_code const& e, boost::shared_ptr h); - void handshake4(asio::error_code const& e, boost::shared_ptr h); + void connected(error_code const& e, boost::shared_ptr h); + void handshake1(error_code const& e, boost::shared_ptr h); + void handshake2(error_code const& e, boost::shared_ptr h); + void handshake3(error_code const& e, boost::shared_ptr h); + void handshake4(error_code const& e, boost::shared_ptr h); void socks_connect(boost::shared_ptr h); - void connect1(asio::error_code const& e, boost::shared_ptr h); - void connect2(asio::error_code const& e, boost::shared_ptr h); - void connect3(asio::error_code const& e, boost::shared_ptr h); + void connect1(error_code const& e, boost::shared_ptr h); + void connect2(error_code const& e, boost::shared_ptr h); + void connect3(error_code const& e, boost::shared_ptr h); // send and receive buffer std::vector m_buffer; diff --git a/libtorrent/include/libtorrent/ssl_stream.hpp b/libtorrent/include/libtorrent/ssl_stream.hpp new file mode 100644 index 000000000..363c819f6 --- /dev/null +++ b/libtorrent/include/libtorrent/ssl_stream.hpp @@ -0,0 +1,227 @@ +/* + +Copyright (c) 2008, Arvid Norberg +All rights reserved. + +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. + +*/ + +#ifndef TORRENT_SSL_STREAM_HPP_INCLUDED +#define TORRENT_SSL_STREAM_HPP_INCLUDED + +#include "libtorrent/socket.hpp" +#if BOOST_VERSION < 103500 +#include +#else +#include +#endif +// openssl seems to believe it owns +// this name in every single scope +#undef set_key + +namespace libtorrent { + +template +class ssl_stream +{ +public: + + explicit ssl_stream(io_service& io_service) + : m_context(io_service, asio::ssl::context::sslv23_client) + , m_sock(io_service, m_context) + { + m_context.set_verify_mode(asio::ssl::context::verify_none); + } + + typedef Stream next_layer_type; + typedef typename Stream::lowest_layer_type lowest_layer_type; + typedef typename Stream::endpoint_type endpoint_type; + typedef typename Stream::protocol_type protocol_type; + typedef typename asio::ssl::stream sock_type; + + typedef boost::function handler_type; + + template + void async_connect(endpoint_type const& endpoint, Handler const& handler) + { + // the connect is split up in the following steps: + // 1. connect to peer + // 2. perform SSL client handshake + + // to avoid unnecessary copying of the handler, + // store it in a shared_ptr + boost::shared_ptr h(new handler_type(handler)); + + m_sock.next_layer().async_connect(endpoint + , boost::bind(&ssl_stream::connected, this, _1, h)); + } + + template + void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) + { + m_sock.async_read_some(buffers, handler); + } + + template + std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec) + { + return m_sock.read_some(buffers, ec); + } + +#ifndef BOOST_NO_EXCEPTIONS + template + std::size_t read_some(Mutable_Buffers const& buffers) + { + return m_sock.read_some(buffers); + } + + template + void io_control(IO_Control_Command& ioc) + { + m_sock.next_layer().io_control(ioc); + } +#endif + + template + void io_control(IO_Control_Command& ioc, error_code& ec) + { + m_sock.next_layer().io_control(ioc, ec); + } + + template + void async_write_some(Const_Buffers const& buffers, Handler const& handler) + { + m_sock.async_write_some(buffers, handler); + } + +#ifndef BOOST_NO_EXCEPTIONS + void bind(endpoint_type const& endpoint) + { + m_sock.next_layer().bind(endpoint); + } +#endif + + void bind(endpoint_type const& endpoint, error_code& ec) + { + m_sock.next_layer().bind(endpoint, ec); + } + +#ifndef BOOST_NO_EXCEPTIONS + void open(protocol_type const& p) + { + m_sock.next_layer().open(p); + } +#endif + + void open(protocol_type const& p, error_code& ec) + { + m_sock.next_layer().open(p, ec); + } + + bool is_open() const + { + return const_cast(m_sock).next_layer().is_open(); + } + +#ifndef BOOST_NO_EXCEPTIONS + void close() + { + m_sock.next_layer().close(); + } +#endif + + void close(error_code& ec) + { + m_sock.next_layer().close(ec); + } + +#ifndef BOOST_NO_EXCEPTIONS + endpoint_type remote_endpoint() const + { + return const_cast(m_sock).next_layer().remote_endpoint(); + } +#endif + + endpoint_type remote_endpoint(error_code& ec) const + { + return const_cast(m_sock).next_layer().remote_endpoint(ec); + } + +#ifndef BOOST_NO_EXCEPTIONS + endpoint_type local_endpoint() const + { + return const_cast(m_sock).next_layer().local_endpoint(); + } +#endif + + endpoint_type local_endpoint(error_code& ec) const + { + return const_cast(m_sock).next_layer().local_endpoint(ec); + } + + io_service& get_io_service() + { + return m_sock.get_io_service(); + } + + lowest_layer_type& lowest_layer() + { + return m_sock.lowest_layer(); + } + + next_layer_type& next_layer() + { + return m_sock.next_layer(); + } + +private: + + void connected(error_code const& e, boost::shared_ptr h) + { + if (e) + { + (*h)(e); + return; + } + + m_sock.async_handshake(asio::ssl::stream_base::client + , boost::bind(&ssl_stream::handshake, this, _1, h)); + } + + void handshake(error_code const& e, boost::shared_ptr h) + { + (*h)(e); + } + + asio::ssl::context m_context; + asio::ssl::stream m_sock; +}; + +} + +#endif + diff --git a/libtorrent/include/libtorrent/stat.hpp b/libtorrent/include/libtorrent/stat.hpp old mode 100755 new mode 100644 index ef9b7780b..ae29671e3 --- a/libtorrent/include/libtorrent/stat.hpp +++ b/libtorrent/include/libtorrent/stat.hpp @@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "libtorrent/size_type.hpp" #include "libtorrent/invariant_check.hpp" @@ -44,88 +45,162 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { - - class TORRENT_EXPORT stat + class TORRENT_EXPORT stat_channel { friend class invariant_access; public: enum { history = 10 }; - stat() - : m_downloaded_payload(0) - , m_uploaded_payload(0) - , m_downloaded_protocol(0) - , m_uploaded_protocol(0) - , m_total_download_payload(0) - , m_total_upload_payload(0) - , m_total_download_protocol(0) - , m_total_upload_protocol(0) - , m_mean_download_rate(0) - , m_mean_upload_rate(0) - , m_mean_download_payload_rate(0) - , m_mean_upload_payload_rate(0) + stat_channel() + : m_counter(0) + , m_total_counter(0) + , m_rate_sum(0) { - std::fill(m_download_rate_history, m_download_rate_history+history, 0.f); - std::fill(m_upload_rate_history, m_upload_rate_history+history, 0.f); - std::fill(m_download_payload_rate_history, m_download_payload_rate_history+history, 0.f); - std::fill(m_upload_payload_rate_history, m_upload_payload_rate_history+history, 0.f); + std::memset(m_rate_history, 0, sizeof(m_rate_history)); } - void operator+=(const stat& s) + void operator+=(stat_channel const& s) { - INVARIANT_CHECK; - - m_downloaded_payload += s.m_downloaded_payload; - m_total_download_payload += s.m_downloaded_payload; - m_downloaded_protocol += s.m_downloaded_protocol; - m_total_download_protocol += s.m_downloaded_protocol; - - m_uploaded_payload += s.m_uploaded_payload; - m_total_upload_payload += s.m_uploaded_payload; - m_uploaded_protocol += s.m_uploaded_protocol; - m_total_upload_protocol += s.m_uploaded_protocol; + m_counter += s.m_counter; + m_total_counter += s.m_counter; } - void received_bytes(int bytes_payload, int bytes_protocol) + void add(int count) { - INVARIANT_CHECK; + TORRENT_ASSERT(count >= 0); - TORRENT_ASSERT(bytes_payload >= 0); - TORRENT_ASSERT(bytes_protocol >= 0); - - m_downloaded_payload += bytes_payload; - m_total_download_payload += bytes_payload; - m_downloaded_protocol += bytes_protocol; - m_total_download_protocol += bytes_protocol; - } - - void sent_bytes(int bytes_payload, int bytes_protocol) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(bytes_payload >= 0); - TORRENT_ASSERT(bytes_protocol >= 0); - - m_uploaded_payload += bytes_payload; - m_total_upload_payload += bytes_payload; - m_uploaded_protocol += bytes_protocol; - m_total_upload_protocol += bytes_protocol; + m_counter += count; + m_total_counter += count; } // should be called once every second void second_tick(float tick_interval); + float rate() const { return m_rate_sum / float(history); } + size_type rate_sum() const { return m_rate_sum; } + size_type total() const { return m_total_counter; } - float upload_rate() const { return m_mean_upload_rate; } - float download_rate() const { return m_mean_download_rate; } + void offset(size_type counter) + { + TORRENT_ASSERT(counter >= 0); + m_total_counter += counter; + } - float upload_payload_rate() const { return m_mean_upload_payload_rate; } - float download_payload_rate() const { return m_mean_download_payload_rate; } + size_type counter() const { return m_counter; } - size_type total_payload_upload() const { return m_total_upload_payload; } - size_type total_payload_download() const { return m_total_download_payload; } + private: - size_type total_protocol_upload() const { return m_total_upload_protocol; } - size_type total_protocol_download() const { return m_total_download_protocol; } +#ifndef NDEBUG + void check_invariant() const + { + int sum = 0; + for (int i = 0; i < history; ++i) sum += m_rate_history[i]; + TORRENT_ASSERT(m_rate_sum == sum); + TORRENT_ASSERT(m_total_counter >= 0); + } +#endif + + // history of rates a few seconds back + int m_rate_history[history]; + + // the accumulator for this second. + int m_counter; + + // total counters + size_type m_total_counter; + + // sum of all elements in m_rate_history + size_type m_rate_sum; + }; + + class TORRENT_EXPORT stat + { + friend class invariant_access; + public: + void operator+=(const stat& s) + { + for (int i = 0; i < num_channels; ++i) + m_stat[i] += s.m_stat[i]; + } + + void received_bytes(int bytes_payload, int bytes_protocol) + { + TORRENT_ASSERT(bytes_payload >= 0); + TORRENT_ASSERT(bytes_protocol >= 0); + + m_stat[download_payload].add(bytes_payload); + m_stat[download_protocol].add(bytes_protocol); + } + + void sent_bytes(int bytes_payload, int bytes_protocol) + { + TORRENT_ASSERT(bytes_payload >= 0); + TORRENT_ASSERT(bytes_protocol >= 0); + + m_stat[upload_payload].add(bytes_payload); + m_stat[upload_protocol].add(bytes_protocol); + } + + // calculate ip protocol overhead + void calc_ip_overhead() + { + int uploaded = m_stat[upload_protocol].counter() + + m_stat[upload_payload].counter(); + int downloaded = m_stat[download_protocol].counter() + + m_stat[download_payload].counter(); + + // IP + TCP headers are 40 bytes per MTU (1460) + // bytes of payload, but at least 40 bytes + m_stat[upload_ip_protocol].add((std::max)(uploaded / 1460, uploaded>0?40:0)); + m_stat[download_ip_protocol].add((std::max)(downloaded / 1460, downloaded>0?40:0)); + + // also account for ACK traffic. That adds to the transfers + // in the opposite direction. Even on connections with symmetric + // transfer rates, it seems to add a penalty. + m_stat[upload_ip_protocol].add((std::max)(downloaded * 40 / 1460, downloaded>0?40:0)); + m_stat[download_ip_protocol].add((std::max)(uploaded * 40 / 1460, uploaded>0?40:0)); + } + + int upload_ip_overhead() const { return m_stat[upload_ip_protocol].counter(); } + int download_ip_overhead() const { return m_stat[download_ip_protocol].counter(); } + + // should be called once every second + void second_tick(float tick_interval) + { + for (int i = 0; i < num_channels; ++i) + m_stat[i].second_tick(tick_interval); + } + + float upload_rate() const + { + return (m_stat[upload_payload].rate_sum() + + m_stat[upload_protocol].rate_sum() + + m_stat[upload_ip_protocol].rate_sum()) + / float(stat_channel::history); + } + + float download_rate() const + { + return (m_stat[download_payload].rate_sum() + + m_stat[download_protocol].rate_sum() + + m_stat[download_ip_protocol].rate_sum()) + / float(stat_channel::history); + } + + float upload_payload_rate() const + { return m_stat[upload_payload].rate(); } + + float download_payload_rate() const + { return m_stat[download_payload].rate(); } + + size_type total_payload_upload() const + { return m_stat[upload_payload].total(); } + size_type total_payload_download() const + { return m_stat[download_payload].total(); } + + size_type total_protocol_upload() const + { return m_stat[upload_protocol].total(); } + size_type total_protocol_download() const + { return m_stat[download_protocol].total(); } // this is used to offset the statistics when a // peer_connection is opened and have some previous @@ -134,63 +209,33 @@ namespace libtorrent { TORRENT_ASSERT(downloaded >= 0); TORRENT_ASSERT(uploaded >= 0); - m_total_download_payload += downloaded; - m_total_upload_payload += uploaded; + m_stat[download_payload].offset(downloaded); + m_stat[upload_payload].offset(uploaded); } + size_type last_payload_downloaded() const + { return m_stat[download_payload].counter(); } + size_type last_payload_uploaded() const + { return m_stat[upload_payload].counter(); } + private: -#ifndef NDEBUG - void check_invariant() const + // these are the channels we keep stats for + enum { - TORRENT_ASSERT(m_mean_upload_rate >= 0); - TORRENT_ASSERT(m_mean_download_rate >= 0); - TORRENT_ASSERT(m_mean_upload_payload_rate >= 0); - TORRENT_ASSERT(m_mean_download_payload_rate >= 0); - TORRENT_ASSERT(m_total_upload_payload >= 0); - TORRENT_ASSERT(m_total_download_payload >= 0); - TORRENT_ASSERT(m_total_upload_protocol >= 0); - TORRENT_ASSERT(m_total_download_protocol >= 0); - } -#endif + upload_payload, + upload_protocol, + upload_ip_protocol, + download_payload, + download_protocol, + download_ip_protocol, + num_channels + }; - // history of download/upload speeds a few seconds back - float m_download_rate_history[history]; - float m_upload_rate_history[history]; - - float m_download_payload_rate_history[history]; - float m_upload_payload_rate_history[history]; - - // the accumulators we are adding the downloads/uploads - // to this second. This only counts the actual payload - // and ignores the bytes sent as protocol chatter. - int m_downloaded_payload; - int m_uploaded_payload; - - // the accumulators we are adding the downloads/uploads - // to this second. This only counts the protocol - // chatter and ignores the actual payload - int m_downloaded_protocol; - int m_uploaded_protocol; - - // total download/upload counters - // only counting payload data - size_type m_total_download_payload; - size_type m_total_upload_payload; - - // total download/upload counters - // only counting protocol chatter - size_type m_total_download_protocol; - size_type m_total_upload_protocol; - - // current mean download/upload rates - float m_mean_download_rate; - float m_mean_upload_rate; - - float m_mean_download_payload_rate; - float m_mean_upload_payload_rate; + stat_channel m_stat[num_channels]; }; } #endif // TORRENT_STAT_HPP_INCLUDED + diff --git a/libtorrent/include/libtorrent/storage.hpp b/libtorrent/include/libtorrent/storage.hpp old mode 100755 new mode 100644 index a7b5e37a4..1733abe8a --- a/libtorrent/include/libtorrent/storage.hpp +++ b/libtorrent/include/libtorrent/storage.hpp @@ -71,6 +71,7 @@ namespace libtorrent class session; struct file_pool; struct disk_io_job; + struct disk_buffer_holder; enum storage_mode_t { @@ -86,11 +87,11 @@ namespace libtorrent #endif TORRENT_EXPORT std::vector > get_filesizes( - torrent_info const& t + file_storage const& t , fs::path p); TORRENT_EXPORT bool match_filesizes( - torrent_info const& t + file_storage const& t , fs::path p , std::vector > const& sizes , bool compact_mode @@ -119,31 +120,33 @@ namespace libtorrent // if allocate_files is true. // allocate_files is true if allocation mode // is set to full and sparse files are supported - virtual void initialize(bool allocate_files) = 0; + // false return value indicates an error + virtual bool initialize(bool allocate_files) = 0; - // may throw file_error if storage for slot does not exist - virtual size_type read(char* buf, int slot, int offset, int size) = 0; + // negative return value indicates an error + virtual int read(char* buf, int slot, int offset, int size) = 0; - // may throw file_error if storage for slot hasn't been allocated - virtual void write(const char* buf, int slot, int offset, int size) = 0; + // negative return value indicates an error + virtual int write(const char* buf, int slot, int offset, int size) = 0; + // non-zero return value indicates an error virtual bool move_storage(fs::path save_path) = 0; // verify storage dependent fast resume entries - virtual bool verify_resume_data(entry& rd, std::string& error) = 0; + virtual bool verify_resume_data(lazy_entry const& rd, std::string& error) = 0; // write storage dependent fast resume entries - virtual void write_resume_data(entry& rd) const = 0; + virtual bool write_resume_data(entry& rd) const = 0; // moves (or copies) the content in src_slot to dst_slot - virtual void move_slot(int src_slot, int dst_slot) = 0; + virtual bool move_slot(int src_slot, int dst_slot) = 0; // swaps the data in slot1 and slot2 - virtual void swap_slots(int slot1, int slot2) = 0; + virtual bool swap_slots(int slot1, int slot2) = 0; // swaps the puts the data in slot1 in slot2, the data in slot2 // in slot3 and the data in slot3 in slot1 - virtual void swap_slots3(int slot1, int slot2, int slot3) = 0; + virtual bool swap_slots3(int slot1, int slot2, int slot3) = 0; // returns the sha1-hash for the data at the given slot virtual sha1_hash hash_for_slot(int slot, partial_hash& h, int piece_size) = 0; @@ -151,21 +154,39 @@ namespace libtorrent // this will close all open files that are opened for // writing. This is called when a torrent has finished // downloading. - virtual void release_files() = 0; + // non-zero return value indicates an error + virtual bool release_files() = 0; + + // this will rename the file specified by index. + virtual bool rename_file(int index, std::string const& new_filename) = 0; // this will close all open files and delete them - virtual void delete_files() = 0; + // non-zero return value indicates an error + virtual bool delete_files() = 0; + + void set_error(std::string const& file, std::string const& msg) const + { + m_error_file = file; + m_error = msg; + } + + std::string const& error() const { return m_error; } + std::string const& error_file() const { return m_error_file; } + void clear_error() { m_error.clear(); m_error_file.clear(); } + + mutable std::string m_error; + mutable std::string m_error_file; virtual ~storage_interface() {} }; typedef storage_interface* (&storage_constructor_type)( - boost::intrusive_ptr, fs::path const& - , file_pool&); + file_storage const&, fs::path const&, file_pool&); TORRENT_EXPORT storage_interface* default_storage_constructor( - boost::intrusive_ptr ti - , fs::path const& path, file_pool& fp); + file_storage const&, fs::path const&, file_pool&); + TORRENT_EXPORT storage_interface* mapped_storage_constructor( + file_storage const&, fs::path const&, file_pool&); struct disk_io_thread; @@ -179,54 +200,38 @@ namespace libtorrent piece_manager( boost::shared_ptr const& torrent - , boost::intrusive_ptr ti + , boost::intrusive_ptr info , fs::path const& path , file_pool& fp , disk_io_thread& io - , storage_constructor_type sc); + , storage_constructor_type sc + , storage_mode_t sm); ~piece_manager(); - bool check_fastresume(aux::piece_checker_data& d - , std::vector& pieces, int& num_pieces, storage_mode_t storage_mode - , std::string& error_msg); - std::pair check_files(std::vector& pieces - , int& num_pieces, boost::recursive_mutex& mutex); - - // frees a buffer that was returned from a read operation - void free_buffer(char* buf); - + boost::intrusive_ptr info() const { return m_info; } void write_resume_data(entry& rd) const; - bool verify_resume_data(entry& rd, std::string& error); - bool is_allocating() const - { return m_state == state_expand_pieces; } - - void mark_failed(int index); - - unsigned long piece_crc( - int slot_index - , int block_size - , piece_picker::block_info const* bi); - - int slot_for(int piece) const; - int piece_for(int slot) const; + void async_check_fastresume(lazy_entry const* resume_data + , boost::function const& handler); + void async_check_files(boost::function const& handler); + + void async_rename_file(int index, std::string const& name + , boost::function const& handler); + void async_read( peer_request const& r , boost::function const& handler - , char* buffer = 0 , int priority = 0); void async_write( peer_request const& r - , char const* buffer + , disk_buffer_holder& buffer , boost::function const& f); void async_hash(int piece, boost::function const& f); - fs::path save_path() const; - void async_release_files( boost::function const& handler = boost::function()); @@ -238,12 +243,49 @@ namespace libtorrent void async_move_storage(fs::path const& p , boost::function const& handler); - // fills the vector that maps all allocated - // slots to the piece that is stored (or - // partially stored) there. -2 is the index - // of unassigned pieces and -1 is unallocated - void export_piece_map(std::vector& pieces - , std::vector const& have) const; + void async_save_resume_data( + boost::function const& handler); + + enum return_t + { + // return values from check_fastresume and check_files + no_error = 0, + need_full_check = -1, + fatal_disk_error = -2, + disk_check_aborted = -3 + }; + + private: + + fs::path save_path() const; + + bool verify_resume_data(lazy_entry const& rd, std::string& error) + { return m_storage->verify_resume_data(rd, error); } + + bool is_allocating() const + { return m_state == state_expand_pieces; } + + void mark_failed(int index); + + std::string const& error() const { return m_storage->error(); } + std::string const& error_file() const { return m_storage->error_file(); } + void clear_error() { m_storage->clear_error(); } + + int slot_for(int piece) const; + int piece_for(int slot) const; + + // helper functions for check_dastresume + int check_no_fastresume(std::string& error); + int check_init_storage(std::string& error); + + // if error is set and return value is 'no_error' or 'need_full_check' + // the error message indicates that the fast resume data was rejected + // if 'fatal_disk_error' is returned, the error message indicates what + // when wrong in the disk access + int check_fastresume(lazy_entry const& rd, std::string& error); + + // this function returns true if the checking is complete + int check_files(int& current_slot, int& have_piece, std::string& error); bool compact_allocation() const { return m_storage_mode == storage_mode_compact; } @@ -251,38 +293,35 @@ namespace libtorrent #ifndef NDEBUG std::string name() const { return m_info->name(); } #endif - - private: bool allocate_slots(int num_slots, bool abort_on_disk = false); - int identify_data( - const std::vector& piece_data - , int current_slot - , std::vector& have_pieces - , int& num_pieces - , const std::multimap& hash_to_piece - , boost::recursive_mutex& mutex); - - size_type read_impl( + int read_impl( char* buf , int piece_index , int offset , int size); - void write_impl( + int write_impl( const char* buf , int piece_index , int offset , int size); + bool check_one_piece(int& have_piece); + int identify_data( + const std::vector& piece_data + , int current_slot); + void switch_to_full_mode(); sha1_hash hash_for_piece_impl(int piece); - void release_files_impl() { m_storage->release_files(); } - void delete_files_impl() { m_storage->delete_files(); } + int release_files_impl() { return m_storage->release_files(); } + int delete_files_impl() { return m_storage->delete_files(); } + int rename_file_impl(int index, std::string const& new_filename) + { return m_storage->rename_file(index, new_filename); } - bool move_storage_impl(fs::path const& save_path); + int move_storage_impl(fs::path const& save_path); int allocate_slot_for_piece(int piece_index); #ifndef NDEBUG @@ -291,12 +330,13 @@ namespace libtorrent void debug_log() const; #endif #endif + boost::intrusive_ptr m_info; + file_storage const& m_files; + boost::scoped_ptr m_storage; storage_mode_t m_storage_mode; - boost::intrusive_ptr m_info; - // slots that haven't had any file storage allocated std::vector m_unallocated_slots; // slots that have file storage, but isn't assigned to a piece @@ -330,8 +370,6 @@ namespace libtorrent state_none, // the file checking is complete state_finished, - // creating the directories - state_create_files, // checking the files state_full_check, // move pieces to their final position @@ -376,9 +414,6 @@ namespace libtorrent // the piece_manager destructs. This is because // the torrent_info object is owned by the torrent. boost::shared_ptr m_torrent; -#ifndef NDEBUG - bool m_resume_data_verified; -#endif }; } diff --git a/libtorrent/include/libtorrent/time.hpp b/libtorrent/include/libtorrent/time.hpp index f4d364e66..ca9e2d85b 100644 --- a/libtorrent/include/libtorrent/time.hpp +++ b/libtorrent/include/libtorrent/time.hpp @@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_TIME_HPP_INCLUDED #include +#include #ifndef _WIN32 #include @@ -86,7 +87,11 @@ namespace libtorrent #else +#if BOOST_VERSION < 103500 #include +#else +#include +#endif #include #include "libtorrent/assert.hpp" @@ -99,6 +104,7 @@ namespace libtorrent time_duration operator/(int rhs) const { return time_duration(diff / rhs); } explicit time_duration(boost::int64_t d) : diff(d) {} time_duration& operator-=(time_duration const& c) { diff -= c.diff; return *this; } + time_duration& operator+=(time_duration const& c) { diff += c.diff; return *this; } time_duration operator+(time_duration const& c) { return time_duration(diff + c.diff); } boost::int64_t diff; }; @@ -118,6 +124,8 @@ namespace libtorrent { ptime() {} explicit ptime(boost::int64_t t): time(t) {} + ptime& operator+=(time_duration rhs) { time += rhs.diff; return *this; } + ptime& operator-=(time_duration rhs) { time -= rhs.diff; return *this; } boost::int64_t time; }; @@ -151,6 +159,9 @@ namespace libtorrent } // asio time_traits +#if BOOST_VERSION >= 103500 +namespace boost { +#endif namespace asio { template<> @@ -171,6 +182,9 @@ namespace asio { return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); } }; } +#if BOOST_VERSION >= 103500 +} +#endif #if defined(__MACH__) diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp old mode 100755 new mode 100644 index 4b61cce2f..b1c2cc541 --- a/libtorrent/include/libtorrent/torrent.hpp +++ b/libtorrent/include/libtorrent/torrent.hpp @@ -70,6 +70,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/storage.hpp" #include "libtorrent/hasher.hpp" #include "libtorrent/assert.hpp" +#include "libtorrent/bitfield.hpp" namespace libtorrent { @@ -79,6 +80,7 @@ namespace libtorrent class piece_manager; struct torrent_plugin; + struct bitfield; namespace aux { @@ -98,20 +100,21 @@ namespace libtorrent torrent( aux::session_impl& ses - , aux::checker_impl& checker , boost::intrusive_ptr tf , fs::path const& save_path , tcp::endpoint const& net_interface , storage_mode_t m_storage_mode , int block_size , storage_constructor_type sc - , bool paused); + , bool paused + , std::vector* resume_data + , int seq + , bool auto_managed); // used with metadata-less torrents // (the metadata is downloaded from the peers) torrent( aux::session_impl& ses - , aux::checker_impl& checker , char const* tracker_url , sha1_hash const& info_hash , char const* name @@ -120,10 +123,15 @@ namespace libtorrent , storage_mode_t m_storage_mode , int block_size , storage_constructor_type sc - , bool paused); + , bool paused + , std::vector* resume_data + , int seq + , bool auto_managed); ~torrent(); + void parse_resume_data(std::vector* resume_data); + // starts the announce timer void start(); @@ -133,10 +141,24 @@ namespace libtorrent , void* userdata); #endif +#ifndef NDEBUG + bool has_peer(peer_connection* p) const + { return m_connections.find(p) != m_connections.end(); } +#endif + // this is called when the torrent has metadata. // it will initialize the storage and the piece-picker void init(); + void on_resume_data_checked(int ret, disk_io_job const& j); + void on_force_recheck(int ret, disk_io_job const& j); + void on_piece_checked(int ret, disk_io_job const& j); + void files_checked(); + void start_checking(); + + int seed_rank(session_settings const& s) const; + + storage_mode_t storage_mode() const { return m_storage_mode; } // this will flag the torrent as aborted. The main // loop in session_impl will check for this state // on all torrents once every second, and take @@ -144,18 +166,19 @@ namespace libtorrent void abort(); bool is_aborted() const { return m_abort; } - // returns true if this torrent is being allocated - // by the checker thread. - bool is_allocating() const; - + torrent_status::state_t state() const { return m_state; } + void set_state(torrent_status::state_t s); + session_settings const& settings() const; aux::session_impl& session() { return m_ses; } - void set_sequenced_download_threshold(int threshold); + void set_sequential_download(bool sd); + bool is_sequential_download() const + { return m_sequential_download; } - bool verify_resume_data(entry& rd, std::string& error) - { TORRENT_ASSERT(m_storage); return m_storage->verify_resume_data(rd, error); } + void set_queue_position(int p); + int queue_position() const { return m_sequence_number; } void second_tick(stat& accumulator, float tick_interval); @@ -164,11 +187,6 @@ namespace libtorrent std::string name() const; - bool check_fastresume(aux::piece_checker_data&); - std::pair check_files(); - void files_checked(std::vector const& - unfinished_pieces); - stat statistics() const { return m_stat; } void add_stats(stat const& s) { m_stat += s; } size_type bytes_left() const; @@ -177,9 +195,21 @@ namespace libtorrent void ip_filter_updated() { m_policy.ip_filter_updated(); } + void set_error(std::string const& msg) { m_error = msg; } + bool has_error() const { return !m_error.empty(); } void pause(); void resume(); - bool is_paused() const { return m_paused; } + + void do_pause(); + void do_resume(); + + bool is_paused() const; + bool is_torrent_paused() const { return m_paused; } + void force_recheck(); + void save_resume_data(); + + bool is_auto_managed() const { return m_auto_managed; } + void auto_managed(bool a); void delete_files(); @@ -230,12 +260,12 @@ namespace libtorrent void request_bandwidth(int channel , boost::intrusive_ptr const& p - , int priority); + , int max_block_size, int priority); void perform_bandwidth_request(int channel , boost::intrusive_ptr const& p , int block_size, int priority); - + void expire_bandwidth(int channel, int amount); void assign_bandwidth(int channel, int amount, int blk); @@ -244,6 +274,8 @@ namespace libtorrent int max_assignable_bandwidth(int channel) const { return m_bandwidth_limit[channel].max_assignable(); } + int bandwidth_queue_size(int channel) const; + // -------------------------------------------- // PEER MANAGEMENT @@ -269,7 +301,8 @@ namespace libtorrent // used by peer_connection to attach itself to a torrent // since incoming connections don't know what torrent // they're a part of until they have received an info_hash. - void attach_peer(peer_connection* p); + // false means attach failed + bool attach_peer(peer_connection* p); // this will remove the peer and make sure all // the pieces it had have their reference counter @@ -280,6 +313,7 @@ namespace libtorrent bool want_more_peers() const; bool try_connect_peer(); + void give_connect_points(int points); // the number of peers that belong to this torrent int num_peers() const { return (int)m_connections.size(); } @@ -296,6 +330,7 @@ namespace libtorrent void resolve_peer_country(boost::intrusive_ptr const& p) const; + void get_full_peer_list(std::vector& v) const; void get_peer_info(std::vector& v); void get_download_queue(std::vector& queue); @@ -309,12 +344,13 @@ namespace libtorrent virtual void tracker_response( tracker_request const& r , std::vector& e, int interval - , int complete, int incomplete); + , int complete, int incomplete, address const& external_ip); virtual void tracker_request_timed_out( tracker_request const& r); virtual void tracker_request_error(tracker_request const& r , int response_code, const std::string& str); - virtual void tracker_warning(std::string const& msg); + virtual void tracker_warning(tracker_request const& req + , std::string const& msg); virtual void tracker_scrape_response(tracker_request const& req , int complete, int incomplete, int downloaded); @@ -341,6 +377,7 @@ namespace libtorrent void force_tracker_request(); void force_tracker_request(ptime); void scrape_tracker(); + ptime const& last_scrape() const { return m_last_scrape; } // sets the username and password that will be sent to // the tracker @@ -356,23 +393,22 @@ namespace libtorrent // returns true if we have downloaded the given piece bool have_piece(int index) const { - TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size()); - return m_have_pieces[index]; + return has_picker()?m_picker->have_piece(index):true; } - const std::vector& pieces() const - { return m_have_pieces; } + int num_have() const + { + return has_picker() + ?m_picker->num_have() + :m_torrent_file->num_pieces(); + } - int num_pieces() const { return m_num_pieces; } - - // when we get a have- or bitfield- messages, this is called for every - // piece a peer has gained. + // when we get a have message, this is called for that piece void peer_has(int index) { if (m_picker.get()) { TORRENT_ASSERT(!is_seed()); - TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size()); m_picker->inc_refcount(index); } #ifndef NDEBUG @@ -383,6 +419,22 @@ namespace libtorrent #endif } + // when we get a bitfield message, this is called for that piece + void peer_has(bitfield const& bits) + { + if (m_picker.get()) + { + TORRENT_ASSERT(!is_seed()); + m_picker->inc_refcount(bits); + } +#ifndef NDEBUG + else + { + TORRENT_ASSERT(is_seed()); + } +#endif + } + void peer_has_all() { if (m_picker.get()) @@ -398,13 +450,11 @@ namespace libtorrent #endif } - // when peer disconnects, this is called for every piece it had void peer_lost(int index) { if (m_picker.get()) { TORRENT_ASSERT(!is_seed()); - TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size()); m_picker->dec_refcount(index); } #ifndef NDEBUG @@ -418,12 +468,8 @@ namespace libtorrent int block_size() const { TORRENT_ASSERT(m_block_size > 0); return m_block_size; } peer_request to_req(piece_block const& p); - // this will tell all peers that we just got his piece - // and also let the piece picker know that we have this piece - // so it wont pick it for download - void announce_piece(int index); - void disconnect_all(); + int disconnect_peers(int num); // this is called wheh the torrent has completed // the download. It will post an event, disconnect @@ -432,17 +478,17 @@ namespace libtorrent // this is the asio callback that is called when a name // lookup for a PEER is completed. - void on_peer_name_lookup(asio::error_code const& e, tcp::resolver::iterator i + void on_peer_name_lookup(error_code const& e, tcp::resolver::iterator i , peer_id pid); // this is the asio callback that is called when a name // lookup for a WEB SEED is completed. - void on_name_lookup(asio::error_code const& e, tcp::resolver::iterator i + void on_name_lookup(error_code const& e, tcp::resolver::iterator i , std::string url, tcp::endpoint proxy); // this is the asio callback that is called when a name // lookup for a proxy for a web seed is completed. - void on_proxy_name_lookup(asio::error_code const& e, tcp::resolver::iterator i + void on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator i , std::string url); // this is called when the torrent has finished. i.e. @@ -451,12 +497,25 @@ namespace libtorrent // completed() is called immediately after it. void finished(); - void async_verify_piece(int piece_index, boost::function const&); + // This is the opposite of finished. It is called if we used + // to be finished but enabled some files for download so that + // we wasn't finished anymore. + void resume_download(); + + void async_verify_piece(int piece_index, boost::function const&); // this is called from the peer_connection // each time a piece has failed the hash // test - void piece_finished(int index, bool passed_hash_check); + void piece_finished(int index, int passed_hash_check); + + // piece_passed is called when a piece passes the hash check + // this will tell all peers that we just got his piece + // and also let the piece picker know that we have this piece + // so it wont pick it for download + void piece_passed(int index); + + // piece_failed is called when a piece fails the hash check void piece_failed(int index); // this will restore the piece picker state for a piece @@ -472,7 +531,9 @@ namespace libtorrent bool is_seed() const { return valid_metadata() - && m_num_pieces == m_torrent_file->num_pieces(); + && (!m_picker + || m_state == torrent_status::seeding + || m_picker->num_have() == m_picker->num_pieces()); } // this is true if we have all the pieces that we want @@ -480,7 +541,7 @@ namespace libtorrent { if (is_seed()) return true; return valid_metadata() && m_torrent_file->num_pieces() - - m_num_pieces - m_picker->num_filtered() == 0; + - m_picker->num_have() - m_picker->num_filtered() == 0; } fs::path save_path() const; @@ -504,10 +565,13 @@ namespace libtorrent void replace_trackers(std::vector const& urls); - torrent_handle get_handle() const; + torrent_handle get_handle(); + + void write_resume_data(entry& rd) const; + void read_resume_data(lazy_entry const& rd); // LOGGING -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING virtual void debug_log(const std::string& line); #endif @@ -531,8 +595,14 @@ namespace libtorrent int max_uploads() const { return m_max_uploads; } void set_max_connections(int limit); int max_connections() const { return m_max_connections; } + void move_storage(fs::path const& save_path); + // renames the file with the given index to the new name + // the name may include a directory path + // returns false on failure + bool rename_file(int index, std::string const& name); + // unless this returns true, new connections must wait // with their initialization. bool ready_for_connections() const @@ -544,7 +614,10 @@ namespace libtorrent // bencoded tree and moves the torrent // to the checker thread for initial checking // of the storage. - void set_metadata(entry const&); + // a return value of false indicates an error + bool set_metadata(lazy_entry const& metadata, std::string& error); + + int sequence_number() const { return m_sequence_number; } private: @@ -552,39 +625,51 @@ namespace libtorrent void on_files_released(int ret, disk_io_job const& j); void on_torrent_paused(int ret, disk_io_job const& j); void on_storage_moved(int ret, disk_io_job const& j); + void on_save_resume_data(int ret, disk_io_job const& j); + void on_file_renamed(int ret, disk_io_job const& j); void on_piece_verified(int ret, disk_io_job const& j - , boost::function f); + , boost::function f); void try_next_tracker(); int prioritize_tracker(int tracker_index); - void on_country_lookup(asio::error_code const& error, tcp::resolver::iterator i + void on_country_lookup(error_code const& error, tcp::resolver::iterator i , boost::intrusive_ptr p) const; bool request_bandwidth_from_session(int channel) const; void update_peer_interest(bool was_finished); + policy m_policy; + + // total time we've been available on this torrent + // does not count when the torrent is stopped or paused + time_duration m_active_time; + + // total time we've been available as a seed on this torrent + // does not count when the torrent is stopped or paused + time_duration m_seeding_time; + + // all time totals of uploaded and downloaded payload + // stored in resume data + size_type m_total_uploaded; + size_type m_total_downloaded; + + // if this torrent is running, this was the time + // when it was started. This is used to have a + // bias towards keeping seeding torrents that + // recently was started, to avoid oscillation + ptime m_started; + + // the last time we initiated a scrape request to + // one of the trackers in this torrent + ptime m_last_scrape; + boost::intrusive_ptr m_torrent_file; - // is set to true when the torrent has - // been aborted. - bool m_abort; - - // is true if this torrent has been paused - bool m_paused; - // this is true from the time when the torrent was - // paused to the time should_request() is called - bool m_just_paused; - tracker_request::event_t m_event; void parse_response(const entry& e, std::vector& peer_list); - // the size of a request block - // each piece is divided into these - // blocks when requested - int m_block_size; - // if this pointer is 0, the torrent is in // a state where the metadata hasn't been // received yet. @@ -613,18 +698,6 @@ namespace libtorrent // the time of next tracker request ptime m_next_request; - // ----------------------------- - // DATA FROM TRACKER RESPONSE - - // the number number of seconds between requests - // from the tracker - int m_duration; - - // the scrape data from the tracker response, this - // is optional and may be -1. - int m_complete; - int m_incomplete; - #ifndef NDEBUG public: #endif @@ -645,28 +718,21 @@ namespace libtorrent // resolving the address for std::set m_resolving_web_seeds; +#ifndef TORRENT_DISABLE_EXTENSIONS + typedef std::list > extension_list_t; + extension_list_t m_extensions; +#endif + // used to resolve the names of web seeds mutable tcp::resolver m_host_resolver; -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - // this is true while there is a country - // resolution in progress. To avoid flodding - // the DNS request queue, only one ip is resolved - // at a time. - mutable bool m_resolving_country; - - // this is true if the user has enabled - // country resolution in this torrent - bool m_resolve_countries; -#endif - // this announce timer is used both // by Local service discovery and // by the DHT. deadline_timer m_announce_timer; static void on_announce_disp(boost::weak_ptr p - , asio::error_code const& e); + , error_code const& e); // this is called once per announce interval void on_announce(); @@ -691,7 +757,6 @@ namespace libtorrent // a back reference to the session // this torrent belongs to. aux::session_impl& m_ses; - aux::checker_impl& m_checker; boost::scoped_ptr m_picker; @@ -702,41 +767,6 @@ namespace libtorrent std::vector m_trackers; // this is an index into m_trackers - int m_last_working_tracker; - int m_currently_trying_tracker; - // the number of connection attempts that has - // failed in a row, this is currently used to - // determine the timeout until next try. - int m_failed_trackers; - - // this is a counter that is decreased every - // second, and when it reaches 0, the policy::pulse() - // is called and the time scaler is reset to 10. - int m_time_scaler; - - // the bitmask that says which pieces we have - std::vector m_have_pieces; - - // the number of pieces we have. The same as - // std::accumulate(m_have_pieces.begin(), - // m_have_pieces.end(), 0) - int m_num_pieces; - - // in case the piece picker hasn't been constructed - // when this settings is set, this variable will keep - // its value until the piece picker is created - int m_sequenced_download_threshold; - - // is false by default and set to - // true when the first tracker reponse - // is received - bool m_got_tracker_response; - - // the upload/download ratio that each peer - // tries to maintain. - // 0 is infinite - float m_ratio; - // the number of bytes that has been // downloaded that failed the hash-test size_type m_total_failed_bytes; @@ -754,20 +784,16 @@ namespace libtorrent // determines the storage state for this torrent. storage_mode_t m_storage_mode; - // defaults to 16 kiB, but can be set by the user - // when creating the torrent - const int m_default_block_size; + // the state of this torrent (queued, checking, downloading) + torrent_status::state_t m_state; - // this is set to false as long as the connections - // of this torrent hasn't been initialized. If we - // have metadata from the start, connections are - // initialized immediately, if we didn't have metadata, - // they are initialized right after files_checked(). - // valid_resume_data() will return false as long as - // the connections aren't initialized, to avoid - // them from altering the piece-picker before it - // has been initialized with files_checked(). - bool m_connections_initialized; + // if there's an error on this torrent, this is the + // error message + std::string m_error; + + // used if there is any resume data + std::vector m_resume_data; + lazy_entry m_resume_entry; // if the torrent is started without metadata, it may // still be given a name until the metadata is received @@ -779,6 +805,13 @@ namespace libtorrent storage_constructor_type m_storage_constructor; + float m_progress; + + // the upload/download ratio that each peer + // tries to maintain. + // 0 is infinite + float m_ratio; + // the maximum number of uploads for this torrent int m_max_uploads; @@ -788,14 +821,18 @@ namespace libtorrent // the maximum number of connections for this torrent int m_max_connections; -#ifndef NDEBUG - bool m_files_checked; -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - typedef std::list > extension_list_t; - extension_list_t m_extensions; -#endif + // the size of a request block + // each piece is divided into these + // blocks when requested + int m_block_size; + + // ----------------------------- + // DATA FROM TRACKER RESPONSE + + // the scrape data from the tracker response, this + // is optional and may be -1. + int m_complete; + int m_incomplete; #ifndef NDEBUG // this is the amount downloaded when this torrent @@ -803,8 +840,103 @@ namespace libtorrent // total_done - m_initial_done <= total_payload_download size_type m_initial_done; #endif + // this is the deficit counter in the Deficit Round Robin + // used to determine which torrent gets the next + // connection attempt. See: + // http://www.ecs.umass.edu/ece/wolf/courses/ECE697J/papers/DRR.pdf + // The quanta assigned to each torrent depends on the torrents + // priority, whether it's seed and the number of connected + // peers it has. This has the effect that some torrents + // will have more connection attempts than other. Each + // connection attempt costs 100 points from the deficit + // counter. points are deducted in try_connect_peer and + // increased in give_connect_points. Outside of the + // torrent object, these points are called connect_points. + int m_deficit_counter; - policy m_policy; + // the number number of seconds between requests + // from the tracker + boost::int16_t m_duration; + + // the sequence number for this torrent, this is a + // monotonically increasing number for each added torrent + boost::int16_t m_sequence_number; + + // the index to the last tracker that worked + boost::int8_t m_last_working_tracker; + + // the tracker that is currently (or was last) + // tried + boost::int8_t m_currently_trying_tracker; + + // the number of connection attempts that has + // failed in a row, this is currently used to + // determine the timeout until next try. + boost::int8_t m_failed_trackers; + + // this is a counter that is decreased every + // second, and when it reaches 0, the policy::pulse() + // is called and the time scaler is reset to 10. + boost::int8_t m_time_scaler; + + // is set to true when the torrent has + // been aborted. + bool m_abort:1; + + // is true if this torrent has been paused + bool m_paused:1; + // this is true from the time when the torrent was + // paused to the time should_request() is called + bool m_just_paused:1; + + // if this is true, libtorrent may pause and resume + // this torrent depending on queuing rules. Torrents + // started with auto_managed flag set may be added in + // a paused state in case there are no available + // slots. + bool m_auto_managed:1; + +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + // this is true while there is a country + // resolution in progress. To avoid flodding + // the DNS request queue, only one ip is resolved + // at a time. + mutable bool m_resolving_country:1; + + // this is true if the user has enabled + // country resolution in this torrent + bool m_resolve_countries:1; +#endif + + // in case the piece picker hasn't been constructed + // when this settings is set, this variable will keep + // its value until the piece picker is created + bool m_sequential_download:1; + + // is false by default and set to + // true when the first tracker reponse + // is received + bool m_got_tracker_response:1; + + // this is set to false as long as the connections + // of this torrent hasn't been initialized. If we + // have metadata from the start, connections are + // initialized immediately, if we didn't have metadata, + // they are initialized right after files_checked(). + // valid_resume_data() will return false as long as + // the connections aren't initialized, to avoid + // them from altering the piece-picker before it + // has been initialized with files_checked(). + bool m_connections_initialized:1; + + // is set to true every time there is an incoming + // connection to this torrent + bool m_has_incoming:1; + + // this is set to true when the files are checked + // before the files are checked, we don't try to + // connect to peers + bool m_files_checked:1; }; inline ptime torrent::next_announce() const diff --git a/libtorrent/include/libtorrent/torrent_handle.hpp b/libtorrent/include/libtorrent/torrent_handle.hpp old mode 100755 new mode 100644 index 24afbe165..25e9bbf21 --- a/libtorrent/include/libtorrent/torrent_handle.hpp +++ b/libtorrent/include/libtorrent/torrent_handle.hpp @@ -100,7 +100,6 @@ namespace libtorrent , num_incomplete(-1) , list_seeds(0) , list_peers(0) - , pieces(0) , num_pieces(0) , total_done(0) , total_wanted_done(0) @@ -114,6 +113,13 @@ namespace libtorrent , storage_mode(storage_mode_sparse) , up_bandwidth_queue(0) , down_bandwidth_queue(0) + , all_time_upload(0) + , all_time_download(0) + , active_time(0) + , seeding_time(0) + , seed_rank(0) + , last_scrape(0) + , has_incoming(false) {} enum state_t @@ -131,6 +137,8 @@ namespace libtorrent state_t state; bool paused; float progress; + std::string error; + boost::posix_time::time_duration next_announce; boost::posix_time::time_duration announce_interval; @@ -187,8 +195,12 @@ namespace libtorrent // (including seeds), but are not necessarily // connected to int list_peers; + + // the number of peers in our peerlist that + // we potentially could connect to + int connect_candidates; - const std::vector* pieces; + bitfield pieces; // this is the number of pieces the client has // downloaded. it is equal to: @@ -236,6 +248,28 @@ namespace libtorrent int up_bandwidth_queue; int down_bandwidth_queue; + + // number of bytes downloaded since torrent was started + // saved and restored from resume data + size_type all_time_upload; + size_type all_time_download; + + // the number of seconds of being active + // and as being a seed, saved and restored + // from resume data + int active_time; + int seeding_time; + + // higher value means more important to seed + int seed_rank; + + // number of seconds since last scrape, or -1 if + // there hasn't been a scrape + int last_scrape; + + // true if there are incoming connections to this + // torrent + bool has_incoming; }; struct TORRENT_EXPORT block_info @@ -278,8 +312,9 @@ namespace libtorrent friend struct aux::session_impl; friend class torrent; - torrent_handle(): m_ses(0), m_chk(0), m_info_hash(0) {} + torrent_handle() {} + void get_full_peer_list(std::vector& v) const; void get_peer_info(std::vector& v) const; torrent_status status() const; void get_download_queue(std::vector& queue) const; @@ -310,6 +345,17 @@ namespace libtorrent bool is_paused() const; void pause() const; void resume() const; + void force_recheck() const; + void save_resume_data() const; + + bool is_auto_managed() const; + void auto_managed(bool m) const; + + int queue_position() const; + void queue_position_up() const; + void queue_position_down() const; + void queue_position_top() const; + void queue_position_bottom() const; #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES void resolve_countries(bool r); @@ -321,6 +367,7 @@ namespace libtorrent // ================ start deprecation ============ + // deprecated in 0.13 // marks the piece with the given index as filtered // it will not be downloaded void filter_piece(int index, bool filter) const TORRENT_DEPRECATED; @@ -349,7 +396,10 @@ namespace libtorrent // to. void use_interface(const char* net_interface) const; - entry write_resume_data() const; + // deprecated in 0.14 + // use save_resume_data() instead. It is async. and + // will return the resume data in an alert + entry write_resume_data() const TORRENT_DEPRECATED; // forces this torrent to reannounce // (make a rerequest from the tracker) @@ -378,7 +428,8 @@ namespace libtorrent void set_download_limit(int limit) const; int download_limit() const; - void set_sequenced_download_threshold(int threshold) const; + void set_sequential_download(bool sd) const; + bool is_sequential_download() const; void set_peer_upload_limit(tcp::endpoint ip, int limit) const; void set_peer_download_limit(tcp::endpoint ip, int limit) const; @@ -403,39 +454,30 @@ namespace libtorrent // post condition: save_path() == save_path if true is returned void move_storage(fs::path const& save_path) const; + void rename_file(int index, fs::path const& new_name) const; - const sha1_hash& info_hash() const - { return m_info_hash; } + sha1_hash info_hash() const; bool operator==(const torrent_handle& h) const - { return m_info_hash == h.m_info_hash; } + { return m_torrent.lock() == h.m_torrent.lock(); } bool operator!=(const torrent_handle& h) const - { return m_info_hash != h.m_info_hash; } + { return m_torrent.lock() != h.m_torrent.lock(); } bool operator<(const torrent_handle& h) const - { return m_info_hash < h.m_info_hash; } + { return m_torrent.lock() < h.m_torrent.lock(); } private: - torrent_handle(aux::session_impl* s, - aux::checker_impl* c, - const sha1_hash& h) - : m_ses(s) - , m_chk(c) - , m_info_hash(h) - { - TORRENT_ASSERT(m_ses != 0); - TORRENT_ASSERT(m_chk != 0); - } + torrent_handle(boost::weak_ptr const& t) + : m_torrent(t) + {} #ifndef NDEBUG void check_invariant() const; #endif - aux::session_impl* m_ses; - aux::checker_impl* m_chk; - sha1_hash m_info_hash; + boost::weak_ptr m_torrent; }; diff --git a/libtorrent/include/libtorrent/torrent_info.hpp b/libtorrent/include/libtorrent/torrent_info.hpp old mode 100755 new mode 100644 index 1eab60902..6c87b475a --- a/libtorrent/include/libtorrent/torrent_info.hpp +++ b/libtorrent/include/libtorrent/torrent_info.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2003, Arvid Norberg +Copyright (c) 2003-2008, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,9 +30,8 @@ POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TORRENT_TORRENT_INFO_HPP_INCLUDE -#define TORRENT_TORRENT_INFO_HPP_INCLUDE - +#ifndef TORRENT_TORRENT_INFO_HPP_INCLUDED +#define TORRENT_TORRENT_INFO_HPP_INCLUDED #include #include @@ -44,54 +43,29 @@ POSSIBILITY OF SUCH DAMAGE. #include #include -#include +#include #ifdef _MSC_VER #pragma warning(pop) #endif #include "libtorrent/entry.hpp" +#include "libtorrent/lazy_entry.hpp" #include "libtorrent/socket.hpp" #include "libtorrent/peer_id.hpp" #include "libtorrent/size_type.hpp" -#include "libtorrent/peer_request.hpp" #include "libtorrent/config.hpp" #include "libtorrent/time.hpp" #include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/assert.hpp" +#include "libtorrent/file_storage.hpp" namespace libtorrent { namespace pt = boost::posix_time; namespace gr = boost::gregorian; - namespace fs = boost::filesystem; - struct TORRENT_EXPORT file_entry - { - file_entry(): offset(0), size(0), file_base(0) {} - - fs::path path; - size_type offset; // the offset of this file inside the torrent - size_type size; // the size of this file - // the offset in the file where the storage starts. - // This is always 0 unless parts of the torrent is - // compressed into a single file, such as a so-called part file. - size_type file_base; - // if the path was incorrectly encoded, this is - // the original corrupt encoded string. It is - // preserved in order to be able to reproduce - // the correct info-hash - boost::shared_ptr orig_path; - }; - - struct TORRENT_EXPORT file_slice - { - int file_index; - size_type offset; - size_type size; - }; - struct TORRENT_EXPORT announce_entry { announce_entry(std::string const& u): url(u), tier(0) {} @@ -99,130 +73,81 @@ namespace libtorrent int tier; }; +#ifndef BOOST_NO_EXCEPTIONS struct TORRENT_EXPORT invalid_torrent_file: std::exception { virtual const char* what() const throw() { return "invalid torrent file"; } }; +#endif + + int TORRENT_EXPORT load_file(fs::path const& filename, std::vector& v); class TORRENT_EXPORT torrent_info : public intrusive_ptr_base { public: - torrent_info(); torrent_info(sha1_hash const& info_hash); - torrent_info(entry const& torrent_file); + torrent_info(lazy_entry const& torrent_file); + torrent_info(char const* buffer, int size); + torrent_info(fs::path const& filename); ~torrent_info(); - entry create_torrent() const; - entry create_info_metadata() const; - void set_comment(char const* str); - void set_creator(char const* str); - void set_piece_size(int size); - void set_hash(int index, sha1_hash const& h); + file_storage const& files() const { return m_files; } + void add_tracker(std::string const& url, int tier = 0); - void add_file(fs::path file, size_type size); - void add_url_seed(std::string const& url); + std::vector const& trackers() const { return m_urls; } - bool remap_files(std::vector const& map); - - std::vector map_block(int piece, size_type offset - , int size, bool storage = false) const; - peer_request map_file(int file, size_type offset, int size - , bool storage = false) const; - std::vector const& url_seeds() const - { - TORRENT_ASSERT(!m_half_metadata); - return m_url_seeds; - } + { return m_url_seeds; } + void add_url_seed(std::string const& url) + { m_url_seeds.push_back(url); } - typedef std::vector::const_iterator file_iterator; - typedef std::vector::const_reverse_iterator reverse_file_iterator; - - // list the files in the torrent file - file_iterator begin_files(bool storage = false) const - { - if (!storage || m_remapped_files.empty()) - return m_files.begin(); - else - return m_remapped_files.begin(); - } - - file_iterator end_files(bool storage = false) const - { - if (!storage || m_remapped_files.empty()) - return m_files.end(); - else - return m_remapped_files.end(); - } - - reverse_file_iterator rbegin_files(bool storage = false) const - { - if (!storage || m_remapped_files.empty()) - return m_files.rbegin(); - else - return m_remapped_files.rbegin(); - } - - reverse_file_iterator rend_files(bool storage = false) const - { - if (!storage || m_remapped_files.empty()) - return m_files.rend(); - else - return m_remapped_files.rend(); - } - - int num_files(bool storage = false) const - { - TORRENT_ASSERT(m_piece_length > 0); - if (!storage || m_remapped_files.empty()) - return (int)m_files.size(); - else - return (int)m_remapped_files.size(); - } - - const file_entry& file_at(int index, bool storage = false) const - { - if (!storage || m_remapped_files.empty()) - { - TORRENT_ASSERT(index >= 0 && index < (int)m_files.size()); - return m_files[index]; - } - else - { - TORRENT_ASSERT(index >= 0 && index < (int)m_remapped_files.size()); - return m_remapped_files[index]; - } - } - - const std::vector& trackers() const { return m_urls; } - - size_type total_size() const { TORRENT_ASSERT(m_piece_length > 0); return m_total_size; } - int piece_length() const { TORRENT_ASSERT(m_piece_length > 0); return m_piece_length; } - int num_pieces() const { TORRENT_ASSERT(m_piece_length > 0); return m_num_pieces; } + size_type total_size() const { return m_files.total_size(); } + int piece_length() const { return m_files.piece_length(); } + int num_pieces() const { return m_files.num_pieces(); } const sha1_hash& info_hash() const { return m_info_hash; } - const std::string& name() const { TORRENT_ASSERT(m_piece_length > 0); return m_name; } + const std::string& name() const { return m_files.name(); } + typedef file_storage::iterator file_iterator; + typedef file_storage::reverse_iterator reverse_file_iterator; + + file_iterator begin_files() const { return m_files.begin(); } + file_iterator end_files() const { return m_files.end(); } + reverse_file_iterator rbegin_files() const { return m_files.rbegin(); } + reverse_file_iterator rend_files() const { return m_files.rend(); } + int num_files() const { return m_files.num_files(); } + file_entry const& file_at(int index) const { return m_files.at(index); } + + file_iterator file_at_offset(size_type offset) const + { return m_files.file_at_offset(offset); } + std::vector map_block(int piece, size_type offset, int size) const + { return m_files.map_block(piece, offset, size); } + peer_request map_file(int file, size_type offset, int size) const + { return m_files.map_file(file, offset, size); } + // ------- start deprecation ------- -// this functionaily will be removed in a future version +// these functions will be removed in a future version + torrent_info(entry const& torrent_file) TORRENT_DEPRECATED; void print(std::ostream& os) const TORRENT_DEPRECATED; // ------- end deprecation ------- - bool is_valid() const { return m_piece_length > 0; } + bool is_valid() const { return m_files.is_valid(); } bool priv() const { return m_private; } - void set_priv(bool v) { m_private = v; } - void convert_file_names(); + int piece_size(int index) const { return m_files.piece_size(index); } - int piece_size(int index) const; + sha1_hash hash_for_piece(int index) const + { return sha1_hash(hash_for_piece_ptr(index)); } - const sha1_hash& hash_for_piece(int index) const + char const* hash_for_piece_ptr(int index) const { TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < (int)m_piece_hash.size()); - TORRENT_ASSERT(!m_half_metadata); - return m_piece_hash[index]; + TORRENT_ASSERT(index < m_files.num_pieces()); + TORRENT_ASSERT(m_piece_hashes); + TORRENT_ASSERT(m_piece_hashes >= m_info_section.get()); + TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size); + return &m_piece_hashes[index*20]; } boost::optional creation_date() const; @@ -237,66 +162,43 @@ namespace libtorrent typedef std::vector > nodes_t; nodes_t const& nodes() const - { - TORRENT_ASSERT(!m_half_metadata); - return m_nodes; - } + { return m_nodes; } + void add_node(std::pair const& node) + { m_nodes.push_back(node); } - void add_node(std::pair const& node); + bool parse_info_section(lazy_entry const& e, std::string& error); - void parse_info_section(entry const& e); - - entry const* extra(char const* key) const - { return m_extra_info.find_key(key); } - - // frees parts of the metadata that isn't - // used by seeds - void seed_free(); + lazy_entry const* info(char const* key) const + { + if (m_info_dict.type() == lazy_entry::none_t) + lazy_bdecode(m_info_section.get(), m_info_section.get() + + m_info_section_size, m_info_dict); + return m_info_dict.dict_find(key); + } void swap(torrent_info& ti); + boost::shared_array metadata() const + { return m_info_section; } + + int metadata_size() const { return m_info_section_size; } + private: - void read_torrent_info(const entry& libtorrent); + bool parse_torrent_file(lazy_entry const& libtorrent, std::string& error); + + file_storage m_files; // the urls to the trackers std::vector m_urls; - std::vector m_url_seeds; - - // the length of one piece - // if this is 0, the torrent_info is - // in an uninitialized state - int m_piece_length; - - // the sha-1 hashes of each piece - std::vector m_piece_hash; - - // the list of files that this torrent consists of - std::vector m_files; - - // this vector is typically empty. If it is not - // empty, it means the user has re-mapped the - // files in this torrent to different names - // on disk. This is only used when reading and - // writing the disk. - std::vector m_remapped_files; - nodes_t m_nodes; - // the sum of all filesizes - size_type m_total_size; - - // the number of pieces in the torrent - int m_num_pieces; - // the hash that identifies this torrent // is mutable because it's calculated // lazily - mutable sha1_hash m_info_hash; + sha1_hash m_info_hash; - std::string m_name; - // if a creation date is found in the torrent file // this will be set to that, otherwise it'll be // 1970, Jan 1 @@ -321,18 +223,19 @@ namespace libtorrent // be announced on the dht bool m_private; - // contains any non-parsed entries from the info-section - // these are kept in order to be able to accurately - // reproduce the info-section when sending the metadata - // to peers. - entry m_extra_info; + // this is a copy of the info section from the torrent. + // it use maintained in this flat format in order to + // make it available through the metadata extension + boost::shared_array m_info_section; + int m_info_section_size; -#ifndef NDEBUG - public: - // this is set to true when seed_free() is called - bool m_half_metadata; - private: -#endif + // this is a pointer into the m_info_section buffer + // pointing to the first byte of the first sha-1 hash + char const* m_piece_hashes; + + // the info section parsed. points into m_info_section + // parsed lazily + mutable lazy_entry m_info_dict; }; } diff --git a/libtorrent/include/libtorrent/tracker_manager.hpp b/libtorrent/include/libtorrent/tracker_manager.hpp old mode 100755 new mode 100644 index 8fec9563c..c9d1f52c6 --- a/libtorrent/include/libtorrent/tracker_manager.hpp +++ b/libtorrent/include/libtorrent/tracker_manager.hpp @@ -71,15 +71,9 @@ namespace libtorrent struct timeout_handler; struct tracker_connection; - // encodes a string using the base64 scheme - TORRENT_EXPORT std::string base64encode(const std::string& s); - // returns -1 if gzip header is invalid or the header size in bytes TORRENT_EXPORT int gzip_header(const char* buf, int size); - TORRENT_EXPORT boost::tuple - parse_url_components(std::string url); - struct TORRENT_EXPORT tracker_request { tracker_request() @@ -121,42 +115,38 @@ namespace libtorrent friend class tracker_manager; request_callback(): m_manager(0) {} virtual ~request_callback() {} - virtual void tracker_warning(std::string const& msg) = 0; + virtual void tracker_warning(tracker_request const& req + , std::string const& msg) = 0; virtual void tracker_scrape_response(tracker_request const& req , int complete, int incomplete, int downloads) {} virtual void tracker_response( - tracker_request const& + tracker_request const& req , std::vector& peers , int interval , int complete - , int incomplete) = 0; + , int incomplete + , address const& external_ip) = 0; virtual void tracker_request_timed_out( - tracker_request const&) = 0; + tracker_request const& req) = 0; virtual void tracker_request_error( - tracker_request const& + tracker_request const& req , int response_code , const std::string& description) = 0; tcp::endpoint m_tracker_address; -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING virtual void debug_log(const std::string& line) = 0; #endif private: tracker_manager* m_manager; }; - TORRENT_EXPORT bool inflate_gzip( - std::vector& buffer - , tracker_request const& req - , request_callback* requester - , int maximum_tracker_response_length); - struct TORRENT_EXPORT timeout_handler : intrusive_ptr_base , boost::noncopyable { - timeout_handler(asio::strand& str); + timeout_handler(io_service& str); void set_timeout(int completion_timeout, int read_timeout); void restart_read_timeout(); @@ -167,12 +157,11 @@ namespace libtorrent private: - void timeout_callback(asio::error_code const&); + void timeout_callback(error_code const&); boost::intrusive_ptr self() { return boost::intrusive_ptr(this); } - asio::strand& m_strand; // used for timeouts // this is set when the request has been sent ptime m_start_time; @@ -194,7 +183,7 @@ namespace libtorrent { tracker_connection(tracker_manager& man , tracker_request const& req - , asio::strand& str + , io_service& ios , address bind_interface , boost::weak_ptr r); @@ -226,7 +215,7 @@ namespace libtorrent , m_abort(false) {} void queue_request( - asio::strand& str + io_service& ios , connection_queue& cc , tracker_request r , std::string const& auth diff --git a/libtorrent/include/libtorrent/udp_socket.hpp b/libtorrent/include/libtorrent/udp_socket.hpp new file mode 100644 index 000000000..77eae5050 --- /dev/null +++ b/libtorrent/include/libtorrent/udp_socket.hpp @@ -0,0 +1,106 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +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. + +*/ + +#ifndef TORRENT_UDP_SOCKET_HPP_INCLUDED +#define TORRENT_UDP_SOCKET_HPP_INCLUDED + +#include "libtorrent/socket.hpp" +#include "libtorrent/session_settings.hpp" + +#include +#include + +namespace libtorrent +{ + class connection_queue; + + class udp_socket + { + public: + typedef boost::function callback_t; + + udp_socket(io_service& ios, callback_t const& c, connection_queue& cc); + + bool is_open() const { return m_ipv4_sock.is_open() || m_ipv6_sock.is_open(); } + io_service& get_io_service() { return m_ipv4_sock.get_io_service(); } + + void send(udp::endpoint const& ep, char const* p, int len, error_code& ec); + void bind(udp::endpoint const& ep, error_code& ec); + void bind(int port); + void close(); + int local_port() const { return m_bind_port; } + + void set_proxy_settings(proxy_settings const& ps); + proxy_settings const& get_proxy_settings() { return m_proxy_settings; } + + private: + + callback_t m_callback; + + void on_read(udp::socket* sock, error_code const& e, std::size_t bytes_transferred); + void on_name_lookup(error_code const& e, tcp::resolver::iterator i); + void on_timeout(); + void on_connect(int ticket); + void on_connected(error_code const& ec); + void handshake1(error_code const& e); + void handshake2(error_code const& e); + void handshake3(error_code const& e); + void handshake4(error_code const& e); + void socks_forward_udp(); + void connect1(error_code const& e); + void connect2(error_code const& e); + + void wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec); + void unwrap(error_code const& e, char const* buf, int size); + + udp::socket m_ipv4_sock; + udp::socket m_ipv6_sock; + udp::endpoint m_v4_ep; + udp::endpoint m_v6_ep; + char m_v4_buf[1600]; + char m_v6_buf[1600]; + int m_bind_port; + + tcp::socket m_socks5_sock; + int m_connection_ticket; + proxy_settings m_proxy_settings; + connection_queue& m_cc; + tcp::resolver m_resolver; + char m_tmp_buf[100]; + bool m_tunnel_packets; + udp::endpoint m_proxy_addr; + }; +} + +#endif + diff --git a/libtorrent/include/libtorrent/udp_tracker_connection.hpp b/libtorrent/include/libtorrent/udp_tracker_connection.hpp old mode 100755 new mode 100644 index 4fba505a4..dd0dea9fe --- a/libtorrent/include/libtorrent/udp_tracker_connection.hpp +++ b/libtorrent/include/libtorrent/udp_tracker_connection.hpp @@ -49,7 +49,7 @@ POSSIBILITY OF SUCH DAMAGE. #pragma warning(pop) #endif -#include "libtorrent/socket.hpp" +#include "libtorrent/udp_socket.hpp" #include "libtorrent/entry.hpp" #include "libtorrent/session_settings.hpp" #include "libtorrent/peer_id.hpp" @@ -65,14 +65,14 @@ namespace libtorrent public: udp_tracker_connection( - asio::strand& str + io_service& ios + , connection_queue& cc , tracker_manager& man , tracker_request const& req - , std::string const& hostname - , unsigned short port , address bind_infc , boost::weak_ptr c - , session_settings const& stn); + , session_settings const& stn + , proxy_settings const& ps); void close(); @@ -89,33 +89,33 @@ namespace libtorrent boost::intrusive_ptr self() { return boost::intrusive_ptr(this); } - void name_lookup(asio::error_code const& error, udp::resolver::iterator i); - void timeout(asio::error_code const& error); + void name_lookup(error_code const& error, udp::resolver::iterator i); + void timeout(error_code const& error); + + void on_receive(error_code const& e, udp::endpoint const& ep + , char const* buf, int size); + void on_connect_response(char const* buf, int size); + void on_announce_response(char const* buf, int size); + void on_scrape_response(char const* buf, int size); void send_udp_connect(); - void connect_response(asio::error_code const& error, std::size_t bytes_transferred); - void send_udp_announce(); - void announce_response(asio::error_code const& error, std::size_t bytes_transferred); - void send_udp_scrape(); - void scrape_response(asio::error_code const& error, std::size_t bytes_transferred); virtual void on_timeout(); tracker_manager& m_man; - asio::strand& m_strand; udp::resolver m_name_lookup; - datagram_socket m_socket; + udp_socket m_socket; udp::endpoint m_target; - udp::endpoint m_sender; int m_transaction_id; boost::int64_t m_connection_id; session_settings const& m_settings; int m_attempts; - std::vector m_buffer; + + action_t m_state; }; } diff --git a/libtorrent/include/libtorrent/upnp.hpp b/libtorrent/include/libtorrent/upnp.hpp index 36d3ced4c..54e832c8a 100644 --- a/libtorrent/include/libtorrent/upnp.hpp +++ b/libtorrent/include/libtorrent/upnp.hpp @@ -58,9 +58,10 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { -// int: external tcp port -// int: external udp port +// int: port-mapping index +// int: external port // std::string: error message +// an empty string as error means success typedef boost::function portmap_callback_t; class upnp : public intrusive_ptr_base @@ -68,64 +69,89 @@ class upnp : public intrusive_ptr_base public: upnp(io_service& ios, connection_queue& cc , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb, bool ignore_nonrouters); + , portmap_callback_t const& cb, bool ignore_nonrouters, void* state = 0); ~upnp(); - // maps the ports, if a port is set to 0 - // it will not be mapped - void set_mappings(int tcp, int udp); + void* drain_state(); + + enum protocol_type { none = 0, udp = 1, tcp = 2 }; + int add_mapping(protocol_type p, int external_port, int local_port); + void delete_mapping(int mapping_index); void discover_device(); void close(); + std::string router_model() + { + mutex_t::scoped_lock l(m_mutex); + return m_model; + } + private: + void discover_device_impl(); static address_v4 upnp_multicast_address; static udp::endpoint upnp_multicast_endpoint; - enum { num_mappings = 2 }; enum { default_lease_time = 3600 }; - void update_mapping(int i, int port); - void resend_request(asio::error_code const& e); + void resend_request(error_code const& e); void on_reply(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred); struct rootdevice; + void next(rootdevice& d, int i); + void update_map(rootdevice& d, int i); + - void on_upnp_xml(asio::error_code const& e + void on_upnp_xml(error_code const& e , libtorrent::http_parser const& p, rootdevice& d , http_connection& c); - void on_upnp_map_response(asio::error_code const& e + void on_upnp_map_response(error_code const& e , libtorrent::http_parser const& p, rootdevice& d , int mapping, http_connection& c); - void on_upnp_unmap_response(asio::error_code const& e + void on_upnp_unmap_response(error_code const& e , libtorrent::http_parser const& p, rootdevice& d , int mapping, http_connection& c); - void on_expire(asio::error_code const& e); + void on_expire(error_code const& e); - void map_port(rootdevice& d, int i); - void unmap_port(rootdevice& d, int i); - void disable(); + void disable(char const* msg); + void return_error(int mapping, int code); void delete_port_mapping(rootdevice& d, int i); void create_port_mapping(http_connection& c, rootdevice& d, int i); void post(upnp::rootdevice const& d, std::string const& soap , std::string const& soap_action); + int num_mappings() const { return int(m_mappings.size()); } + + struct global_mapping_t + { + global_mapping_t() + : protocol(none) + , external_port(0) + , local_port(0) + {} + int protocol; + int external_port; + int local_port; + }; + struct mapping_t { + enum action_t { action_none, action_add, action_delete }; mapping_t() - : need_update(false) + : action(action_none) , local_port(0) , external_port(0) - , protocol(1) + , protocol(none) + , failcount(0) {} // the time the port mapping will expire ptime expires; - bool need_update; + int action; // the local port for this mapping. If this is set // to 0, the mapping is not in use @@ -136,8 +162,11 @@ private: // should announce to others int external_port; - // 1 = udp, 0 = tcp + // 2 = udp, 1 = tcp int protocol; + + // the number of times this mapping has failed + int failcount; }; struct rootdevice @@ -147,8 +176,6 @@ private: , supports_specific_external(true) , disabled(false) { - mapping[0].protocol = 0; - mapping[1].protocol = 1; #ifndef NDEBUG magic = 1337; #endif @@ -161,7 +188,7 @@ private: magic = 0; } #endif - + // the interface url, through which the list of // supported interfaces are fetched std::string url; @@ -171,7 +198,7 @@ private: // either the WANIP namespace or the WANPPP namespace char const* service_namespace; - mapping_t mapping[num_mappings]; + std::vector mapping; std::string hostname; int port; @@ -201,8 +228,13 @@ private: { return url < rhs.url; } }; - int m_udp_local_port; - int m_tcp_local_port; + struct upnp_state_t + { + std::vector mappings; + std::set devices; + }; + + std::vector m_mappings; std::string const& m_user_agent; @@ -214,9 +246,7 @@ private: // current retry count int m_retry_count; - asio::io_service& m_io_service; - - asio::strand m_strand; + io_service& m_io_service; // the udp socket used to send and receive // multicast messages on the network @@ -231,10 +261,15 @@ private: bool m_disabled; bool m_closing; - bool m_ignore_outside_network; + bool m_ignore_non_routers; connection_queue& m_cc; + typedef boost::mutex mutex_t; + mutex_t m_mutex; + + std::string m_model; + #ifdef TORRENT_UPNP_LOGGING std::ofstream m_log; #endif diff --git a/libtorrent/include/libtorrent/variant_stream.hpp b/libtorrent/include/libtorrent/variant_stream.hpp index bbe3d964d..3551f5c9e 100644 --- a/libtorrent/include/libtorrent/variant_stream.hpp +++ b/libtorrent/include/libtorrent/variant_stream.hpp @@ -21,7 +21,11 @@ # include # include +#if BOOST_VERSION < 103500 #include +#else +#include +#endif # define NETWORK_VARIANT_STREAM_LIMIT 5 @@ -48,7 +52,7 @@ namespace aux template struct io_control_visitor_ec: boost::static_visitor<> { - io_control_visitor_ec(IO_Control_Command& ioc, asio::error_code& ec_) + io_control_visitor_ec(IO_Control_Command& ioc, error_code& ec_) : ioc(ioc), ec(ec_) {} template @@ -61,7 +65,7 @@ namespace aux {} IO_Control_Command& ioc; - asio::error_code& ec; + error_code& ec; }; template @@ -112,7 +116,7 @@ namespace aux struct bind_visitor_ec : boost::static_visitor<> { - bind_visitor_ec(EndpointType const& ep, asio::error_code& ec_) + bind_visitor_ec(EndpointType const& ep, error_code& ec_) : endpoint(ep) , ec(ec_) {} @@ -124,7 +128,7 @@ namespace aux void operator()(boost::blank) const {} EndpointType const& endpoint; - asio::error_code& ec; + error_code& ec; }; template @@ -150,7 +154,7 @@ namespace aux struct open_visitor_ec : boost::static_visitor<> { - open_visitor_ec(Protocol const& p, asio::error_code& ec_) + open_visitor_ec(Protocol const& p, error_code& ec_) : proto(p) , ec(ec_) {} @@ -162,7 +166,7 @@ namespace aux void operator()(boost::blank) const {} Protocol const& proto; - asio::error_code& ec; + error_code& ec; }; template @@ -182,12 +186,26 @@ namespace aux Protocol const& proto; }; +// -------------- is_open ----------- + + struct is_open_visitor + : boost::static_visitor + { + is_open_visitor() {} + + template + bool operator()(T const* p) const + { return p->is_open(); } + + bool operator()(boost::blank) const { return false; } + }; + // -------------- close ----------- struct close_visitor_ec : boost::static_visitor<> { - close_visitor_ec(asio::error_code& ec_) + close_visitor_ec(error_code& ec_) : ec(ec_) {} @@ -197,7 +215,7 @@ namespace aux void operator()(boost::blank) const {} - asio::error_code& ec; + error_code& ec; }; struct close_visitor @@ -216,18 +234,18 @@ namespace aux struct remote_endpoint_visitor_ec : boost::static_visitor { - remote_endpoint_visitor_ec(asio::error_code& ec) - : error_code(ec) + remote_endpoint_visitor_ec(error_code& ec_) + : ec(ec_) {} template - EndpointType operator()(T* p) const - { return p->remote_endpoint(error_code); } + EndpointType operator()(T const* p) const + { return p->remote_endpoint(ec); } EndpointType operator()(boost::blank) const { return EndpointType(); } - asio::error_code& error_code; + error_code& ec; }; template @@ -235,27 +253,66 @@ namespace aux : boost::static_visitor { template - EndpointType operator()(T* p) const + EndpointType operator()(T const* p) const { return p->remote_endpoint(); } EndpointType operator()(boost::blank) const { return EndpointType(); } }; +// -------------- set_option ----------- + + template + struct set_option_visitor + : boost::static_visitor<> + { + set_option_visitor(SettableSocketOption const& opt) + : opt_(opt) + {} + + template + void operator()(T* p) const + { p->set_option(opt_); } + + void operator()(boost::blank) const {} + + SettableSocketOption const& opt_; + }; + + template + struct set_option_visitor_ec + : boost::static_visitor + { + set_option_visitor_ec(SettableSocketOption const& opt, error_code& ec) + : opt_(opt) + , ec_(ec) + {} + + template + error_code operator()(T* p) const + { return p->set_option(opt_, ec_); } + + error_code operator()(boost::blank) const + { return ec_; } + + SettableSocketOption const& opt_; + error_code& ec_; + }; + // -------------- local_endpoint ----------- template struct local_endpoint_visitor_ec : boost::static_visitor { - local_endpoint_visitor_ec(asio::error_code& ec) - : error_code(ec) + local_endpoint_visitor_ec(error_code& ec_) + : ec(ec_) {} template - EndpointType operator()(T* p) const + EndpointType operator()(T const* p) const { - return p->local_endpoint(error_code); + return p->local_endpoint(ec); } EndpointType operator()(boost::blank) const @@ -263,7 +320,7 @@ namespace aux return EndpointType(); } - asio::error_code& error_code; + error_code& ec; }; template @@ -271,7 +328,7 @@ namespace aux : boost::static_visitor { template - EndpointType operator()(T* p) const + EndpointType operator()(T const* p) const { return p->local_endpoint(); } @@ -319,7 +376,7 @@ namespace aux std::size_t operator()(T* p) const { return p->read_some(buffers); } - std::size_t operator()(boost::blank) const + std::size_t operator()(boost::blank) const { return 0; } Mutable_Buffers const& buffers; @@ -329,7 +386,7 @@ namespace aux struct read_some_visitor_ec : boost::static_visitor { - read_some_visitor_ec(Mutable_Buffers const& buffers, asio::error_code& ec_) + read_some_visitor_ec(Mutable_Buffers const& buffers, error_code& ec_) : buffers(buffers) , ec(ec_) {} @@ -338,11 +395,11 @@ namespace aux std::size_t operator()(T* p) const { return p->read_some(buffers, ec); } - std::size_t operator()(boost::blank) const + std::size_t operator()(boost::blank) const { return 0; } Mutable_Buffers const& buffers; - asio::error_code& ec; + error_code& ec; }; // -------------- async_write_some ----------- @@ -374,12 +431,12 @@ namespace aux struct in_avail_visitor_ec : boost::static_visitor { - in_avail_visitor_ec(asio::error_code& ec_) + in_avail_visitor_ec(error_code& ec_) : ec(ec_) {} template - std::size_t operator()(T* p) const + std::size_t operator()(T const* p) const { return p->in_avail(ec); } @@ -389,14 +446,14 @@ namespace aux return 0; } - asio::error_code& ec; + error_code& ec; }; struct in_avail_visitor : boost::static_visitor { template - std::size_t operator()(T* p) const + std::size_t operator()(T const* p) const { return p->in_avail(); } @@ -414,7 +471,7 @@ namespace aux template IOService& operator()(T* p) const { - return p->io_service(); + return p->get_io_service(); } IOService& operator()(boost::blank) const @@ -471,11 +528,13 @@ public: typedef typename S0::endpoint_type endpoint_type; typedef typename S0::protocol_type protocol_type; - explicit variant_stream() : m_variant(boost::blank()) {} + explicit variant_stream(io_service& ios) + : m_io_service(ios), m_variant(boost::blank()) {} template - void instantiate(asio::io_service& ios) + void instantiate(io_service& ios) { + TORRENT_ASSERT(&ios == &m_io_service); std::auto_ptr owned(new S(ios)); boost::apply_visitor(aux::delete_visitor(), m_variant); m_variant = owned.get(); @@ -485,7 +544,7 @@ public: template S& get() { - return *boost::get(m_variant); + return *boost::get(m_variant); } bool instantiated() const @@ -499,7 +558,7 @@ public: } template - std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec) + std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec) { TORRENT_ASSERT(instantiated()); return boost::apply_visitor( @@ -557,7 +616,7 @@ public: } template - void io_control(IO_Control_Command& ioc, asio::error_code& ec) + void io_control(IO_Control_Command& ioc, error_code& ec) { TORRENT_ASSERT(instantiated()); boost::apply_visitor( @@ -572,7 +631,7 @@ public: boost::apply_visitor(aux::bind_visitor(endpoint), m_variant); } - void bind(endpoint_type const& endpoint, asio::error_code& ec) + void bind(endpoint_type const& endpoint, error_code& ec) { TORRENT_ASSERT(instantiated()); boost::apply_visitor( @@ -586,7 +645,7 @@ public: boost::apply_visitor(aux::open_visitor(p), m_variant); } - void open(protocol_type const& p, asio::error_code& ec) + void open(protocol_type const& p, error_code& ec) { TORRENT_ASSERT(instantiated()); boost::apply_visitor( @@ -594,13 +653,18 @@ public: ); } + bool is_open() const + { + return boost::apply_visitor(aux::is_open_visitor(), m_variant); + } + void close() { if (!instantiated()) return; boost::apply_visitor(aux::close_visitor(), m_variant); } - void close(asio::error_code& ec) + void close(error_code& ec) { if (!instantiated()) return; boost::apply_visitor( @@ -608,13 +672,13 @@ public: ); } - std::size_t in_avail() + std::size_t in_avail() const { TORRENT_ASSERT(instantiated()); return boost::apply_visitor(aux::in_avail_visitor(), m_variant); } - std::size_t in_avail(asio::error_code& ec) + std::size_t in_avail(error_code& ec) const { TORRENT_ASSERT(instantiated()); return boost::apply_visitor( @@ -622,13 +686,13 @@ public: ); } - endpoint_type remote_endpoint() + endpoint_type remote_endpoint() const { TORRENT_ASSERT(instantiated()); return boost::apply_visitor(aux::remote_endpoint_visitor(), m_variant); } - endpoint_type remote_endpoint(asio::error_code& ec) + endpoint_type remote_endpoint(error_code& ec) const { TORRENT_ASSERT(instantiated()); return boost::apply_visitor( @@ -636,13 +700,29 @@ public: ); } - endpoint_type local_endpoint() + template + void set_option(SettableSocketOption const& opt) + { + TORRENT_ASSERT(instantiated()); + boost::apply_visitor(aux::set_option_visitor(opt) + , m_variant); + } + + template + error_code set_option(SettableSocketOption const& opt, error_code& ec) + { + TORRENT_ASSERT(instantiated()); + return boost::apply_visitor(aux::set_option_visitor_ec(opt, ec) + , m_variant); + } + + endpoint_type local_endpoint() const { TORRENT_ASSERT(instantiated()); return boost::apply_visitor(aux::local_endpoint_visitor(), m_variant); } - endpoint_type local_endpoint(asio::error_code& ec) + endpoint_type local_endpoint(error_code& ec) const { TORRENT_ASSERT(instantiated()); return boost::apply_visitor( @@ -650,12 +730,9 @@ public: ); } - asio::io_service& io_service() + io_service& get_io_service() { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::io_service_visitor(), m_variant - ); + return m_io_service; } lowest_layer_type& lowest_layer() @@ -667,6 +744,7 @@ public: } private: + io_service& m_io_service; variant_type m_variant; }; diff --git a/libtorrent/include/libtorrent/version.hpp b/libtorrent/include/libtorrent/version.hpp old mode 100755 new mode 100644 index c2cc705eb..06b1bbe13 --- a/libtorrent/include/libtorrent/version.hpp +++ b/libtorrent/include/libtorrent/version.hpp @@ -34,8 +34,8 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_VERSION_HPP_INCLUDED #define LIBTORRENT_VERSION_MAJOR 0 -#define LIBTORRENT_VERSION_MINOR 13 +#define LIBTORRENT_VERSION_MINOR 14 -#define LIBTORRENT_VERSION "0.13.1.0" +#define LIBTORRENT_VERSION "0.14.0.0" #endif diff --git a/libtorrent/include/libtorrent/web_peer_connection.hpp b/libtorrent/include/libtorrent/web_peer_connection.hpp old mode 100755 new mode 100644 index 10161370f..f8e7af99f --- a/libtorrent/include/libtorrent/web_peer_connection.hpp +++ b/libtorrent/include/libtorrent/web_peer_connection.hpp @@ -70,8 +70,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/config.hpp" // parse_url #include "libtorrent/tracker_manager.hpp" -// http_parser -#include "libtorrent/http_tracker_connection.hpp" +#include "libtorrent/http_parser.hpp" namespace libtorrent { @@ -103,9 +102,9 @@ namespace libtorrent // called from the main loop when this connection has any // work to do. - void on_sent(asio::error_code const& error + void on_sent(error_code const& error , std::size_t bytes_transferred); - void on_receive(asio::error_code const& error + void on_receive(error_code const& error , std::size_t bytes_transferred); std::string const& url() const { return m_url; } @@ -123,7 +122,7 @@ namespace libtorrent void write_cancel(peer_request const& r) { incoming_reject_request(r); } void write_have(int index) {} - void write_piece(peer_request const& r, char* buffer) { TORRENT_ASSERT(false); } + void write_piece(peer_request const& r, disk_buffer_holder& buffer) { TORRENT_ASSERT(false); } void write_keepalive() {} void on_connected(); void write_reject_request(peer_request const&) {} diff --git a/libtorrent/src/GeoIP.c b/libtorrent/src/GeoIP.c new file mode 100644 index 000000000..6ca0e51d8 --- /dev/null +++ b/libtorrent/src/GeoIP.c @@ -0,0 +1,1038 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* GeoIP.c + * + * Copyright (C) 2006 MaxMind LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libtorrent/GeoIP.h" + +#ifndef WIN32 +#include +#include +#include /* For ntohl */ +#include + +#include + +#else +#include +#include +#define snprintf _snprintf +#endif +#include +#include +#include +#include +#include +#include /* for fstat */ +#include /* for fstat */ + +#ifdef HAVE_STDINT_H +#include /* For uint32_t */ +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE -1 +#endif + +#define COUNTRY_BEGIN 16776960 +#define STATE_BEGIN_REV0 16700000 +#define STATE_BEGIN_REV1 16000000 +#define STRUCTURE_INFO_MAX_SIZE 20 +#define DATABASE_INFO_MAX_SIZE 100 +#define MAX_ORG_RECORD_LENGTH 300 +#define US_OFFSET 1 +#define CANADA_OFFSET 677 +#define WORLD_OFFSET 1353 +#define FIPS_RANGE 360 + +#define CHECK_ERR(err, msg) { \ + if (err != Z_OK) { \ + fprintf(stderr, "%s error: %d\n", msg, err); \ + exit(1); \ + } \ +} + +const char GeoIP_country_code[253][3] = { "--","AP","EU","AD","AE","AF","AG","AI","AL","AM","AN", + "AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB", + "BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO", + "BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD", + "CF","CG","CH","CI","CK","CL","CM","CN","CO","CR", + "CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO", + "DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ", + "FK","FM","FO","FR","FX","GA","GB","GD","GE","GF", + "GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT", + "GU","GW","GY","HK","HM","HN","HR","HT","HU","ID", + "IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO", + "JP","KE","KG","KH","KI","KM","KN","KP","KR","KW", + "KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT", + "LU","LV","LY","MA","MC","MD","MG","MH","MK","ML", + "MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV", + "MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI", + "NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF", + "PG","PH","PK","PL","PM","PN","PR","PS","PT","PW", + "PY","QA","RE","RO","RU","RW","SA","SB","SC","SD", + "SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO", + "SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH", + "TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW", + "TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE", + "VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA", + "ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE", + "BL","MF"}; + +const char GeoIP_country_code3[253][4] = { "--","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","ANT", + "AGO","AQ","ARG","ASM","AUT","AUS","ABW","AZE","BIH","BRB", + "BGD","BEL","BFA","BGR","BHR","BDI","BEN","BMU","BRN","BOL", + "BRA","BHS","BTN","BV","BWA","BLR","BLZ","CAN","CC","COD", + "CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI", + "CUB","CPV","CX","CYP","CZE","DEU","DJI","DNK","DMA","DOM", + "DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN","FJI", + "FLK","FSM","FRO","FRA","FX","GAB","GBR","GRD","GEO","GUF", + "GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","GS","GTM", + "GUM","GNB","GUY","HKG","HM","HND","HRV","HTI","HUN","IDN", + "IRL","ISR","IND","IO","IRQ","IRN","ISL","ITA","JAM","JOR", + "JPN","KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT", + "CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU", + "LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI", + "MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV", + "MWI","MEX","MYS","MOZ","NAM","NCL","NER","NFK","NGA","NIC", + "NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER","PYF", + "PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW", + "PRY","QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN", + "SWE","SGP","SHN","SVN","SJM","SVK","SLE","SMR","SEN","SOM", + "SUR","STP","SLV","SYR","SWZ","TCA","TCD","TF","TGO","THA", + "TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN", + "TZA","UKR","UGA","UM","USA","URY","UZB","VAT","VCT","VEN", + "VGB","VIR","VNM","VUT","WLF","WSM","YEM","YT","SRB","ZAF", + "ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY", + "BLM","MAF"}; + +const char * GeoIP_country_name[253] = {"N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles", + "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados", + "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia", + "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the", + "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica", + "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic", + "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji", + "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana", + "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala", + "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia", + "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan", + "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait", + "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania", + "Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali", + "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives", + "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua", + "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia", + "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau", + "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan", + "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname", + "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand", + "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan", + "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela", + "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa", + "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey", + "Saint Barthelemy","Saint Martin"}; + +/* Possible continent codes are AF, AS, EU, NA, OC, SA for Africa, Asia, Europe, North America, Oceania +and South America. */ + +const char GeoIP_country_continent[253][3] = {"--","AS","EU","EU","AS","AS","SA","SA","EU","AS","SA", + "AF","AN","SA","OC","EU","OC","SA","AS","EU","SA", + "AS","EU","AF","EU","AS","AF","AF","SA","AS","SA", + "SA","SA","AS","AF","AF","EU","SA","NA","AS","AF", + "AF","AF","EU","AF","OC","SA","AF","AS","SA","SA", + "SA","AF","AS","AS","EU","EU","AF","EU","SA","SA", + "AF","SA","EU","AF","AF","AF","EU","AF","EU","OC", + "SA","OC","EU","EU","EU","AF","EU","SA","AS","SA", + "AF","EU","SA","AF","AF","SA","AF","EU","SA","SA", + "OC","AF","SA","AS","AF","SA","EU","SA","EU","AS", + "EU","AS","AS","AS","AS","AS","EU","EU","SA","AS", + "AS","AF","AS","AS","OC","AF","SA","AS","AS","AS", + "SA","AS","AS","AS","SA","EU","AS","AF","AF","EU", + "EU","EU","AF","AF","EU","EU","AF","OC","EU","AF", + "AS","AS","AS","OC","SA","AF","SA","EU","AF","AS", + "AF","NA","AS","AF","AF","OC","AF","OC","AF","SA", + "EU","EU","AS","OC","OC","OC","AS","SA","SA","OC", + "OC","AS","AS","EU","SA","OC","SA","AS","EU","OC", + "SA","AS","AF","EU","AS","AF","AS","OC","AF","AF", + "EU","AS","AF","EU","EU","EU","AF","EU","AF","AF", + "SA","AF","SA","AS","AF","SA","AF","AF","AF","AS", + "AS","OC","AS","AF","OC","AS","AS","SA","OC","AS", + "AF","EU","AF","OC","NA","SA","AS","EU","SA","SA", + "SA","SA","AS","OC","OC","OC","AS","AF","EU","AF", + "AF","EU","AF","--","--","--","EU","EU","EU","EU", + "SA","SA"}; + +const char * GeoIPDBDescription[NUM_DB_TYPES] = {NULL, "GeoIP Country Edition", "GeoIP City Edition, Rev 1", "GeoIP Region Edition, Rev 1", "GeoIP ISP Edition", "GeoIP Organization Edition", "GeoIP City Edition, Rev 0", "GeoIP Region Edition, Rev 0","GeoIP Proxy Edition","GeoIP ASNum Edition","GeoIP Netspeed Edition","GeoIP Domain Name Edition"}; + +char * custom_directory = NULL; + +void GeoIP_setup_custom_directory (char * dir) { + custom_directory = dir; +} +/* +char *_GeoIP_full_path_to(const char *file_name) { + int len; + char *path = malloc(sizeof(char) * 1024); + + if (custom_directory == NULL){ +#ifndef WIN32 + memset(path, 0, sizeof(char) * 1024); + snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", GEOIPDATADIR, file_name); +#else + char buf[MAX_PATH], *p, *q = NULL; + memset(buf, 0, sizeof(buf)); + len = GetModuleFileName(GetModuleHandle(NULL), buf, sizeof(buf) - 1); + for (p = buf + len; p > buf; p--) + if (*p == '\\') + { + if (!q) + q = p; + else + *p = '/'; + } + *q = 0; + memset(path, 0, sizeof(char) * 1024); + snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", buf, file_name); +#endif + } else { + len = strlen(custom_directory); + if (custom_directory[len-1] != '/') { + snprintf(path, sizeof(char) * 1024 - 1, "%s/%s",custom_directory, file_name); + } else { + snprintf(path, sizeof(char) * 1024 - 1, "%s%s", custom_directory, file_name); + } + } + return path; +} + +char ** GeoIPDBFileName = NULL; + +void _GeoIP_setup_dbfilename() { + if (NULL == GeoIPDBFileName) { + GeoIPDBFileName = malloc(sizeof(char *) * NUM_DB_TYPES); + memset(GeoIPDBFileName, 0, sizeof(char *) * NUM_DB_TYPES); + + GeoIPDBFileName[GEOIP_COUNTRY_EDITION] = _GeoIP_full_path_to("GeoIP.dat"); + GeoIPDBFileName[GEOIP_REGION_EDITION_REV0] = _GeoIP_full_path_to("GeoIPRegion.dat"); + GeoIPDBFileName[GEOIP_REGION_EDITION_REV1] = _GeoIP_full_path_to("GeoIPRegion.dat"); + GeoIPDBFileName[GEOIP_CITY_EDITION_REV0] = _GeoIP_full_path_to("GeoIPCity.dat"); + GeoIPDBFileName[GEOIP_CITY_EDITION_REV1] = _GeoIP_full_path_to("GeoIPCity.dat"); + GeoIPDBFileName[GEOIP_ISP_EDITION] = _GeoIP_full_path_to("GeoIPISP.dat"); + GeoIPDBFileName[GEOIP_ORG_EDITION] = _GeoIP_full_path_to("GeoIPOrg.dat"); + GeoIPDBFileName[GEOIP_PROXY_EDITION] = _GeoIP_full_path_to("GeoIPProxy.dat"); + GeoIPDBFileName[GEOIP_ASNUM_EDITION] = _GeoIP_full_path_to("GeoIPASNum.dat"); + GeoIPDBFileName[GEOIP_NETSPEED_EDITION] = _GeoIP_full_path_to("GeoIPNetSpeed.dat"); + GeoIPDBFileName[GEOIP_DOMAIN_EDITION] = _GeoIP_full_path_to("GeoIPDomain.dat"); + } +} +*/ + +static +int _file_exists(const char *file_name) { + struct stat file_stat; + return( (stat(file_name, &file_stat) == 0) ? 1:0); +} +/* +int GeoIP_db_avail(int type) { + const char * filePath; + if (type < 0 || type >= NUM_DB_TYPES) { + return 0; + } + _GeoIP_setup_dbfilename(); + filePath = GeoIPDBFileName[type]; + if (NULL == filePath) { + return 0; + } + return _file_exists(filePath); +} +*/ +static +void _setup_segments(GeoIP * gi) { + int i, j; + unsigned char delim[3]; + unsigned char buf[SEGMENT_RECORD_LENGTH]; + + gi->databaseSegments = NULL; + + /* default to GeoIP Country Edition */ + gi->databaseType = GEOIP_COUNTRY_EDITION; + gi->record_length = STANDARD_RECORD_LENGTH; + fseek(gi->GeoIPDatabase, -3l, SEEK_END); + for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) { + fread(delim, 1, 3, gi->GeoIPDatabase); + if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) { + fread(&gi->databaseType, 1, 1, gi->GeoIPDatabase); + if (gi->databaseType >= 106) { + /* backwards compatibility with databases from April 2003 and earlier */ + gi->databaseType -= 105; + } + + if (gi->databaseType == GEOIP_REGION_EDITION_REV0) { + /* Region Edition, pre June 2003 */ + gi->databaseSegments = malloc(sizeof(int)); + gi->databaseSegments[0] = STATE_BEGIN_REV0; + } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) { + /* Region Edition, post June 2003 */ + gi->databaseSegments = malloc(sizeof(int)); + gi->databaseSegments[0] = STATE_BEGIN_REV1; + } else if (gi->databaseType == GEOIP_CITY_EDITION_REV0 || + gi->databaseType == GEOIP_CITY_EDITION_REV1 || + gi->databaseType == GEOIP_ORG_EDITION || + gi->databaseType == GEOIP_ISP_EDITION || + gi->databaseType == GEOIP_ASNUM_EDITION) { + /* City/Org Editions have two segments, read offset of second segment */ + gi->databaseSegments = malloc(sizeof(int)); + gi->databaseSegments[0] = 0; + fread(buf, SEGMENT_RECORD_LENGTH, 1, gi->GeoIPDatabase); + for (j = 0; j < SEGMENT_RECORD_LENGTH; j++) { + gi->databaseSegments[0] += (buf[j] << (j * 8)); + } + if (gi->databaseType == GEOIP_ORG_EDITION || + gi->databaseType == GEOIP_ISP_EDITION) + gi->record_length = ORG_RECORD_LENGTH; + } + break; + } else { + fseek(gi->GeoIPDatabase, -4l, SEEK_CUR); + } + } + if (gi->databaseType == GEOIP_COUNTRY_EDITION || + gi->databaseType == GEOIP_PROXY_EDITION || + gi->databaseType == GEOIP_NETSPEED_EDITION) { + gi->databaseSegments = malloc(sizeof(int)); + gi->databaseSegments[0] = COUNTRY_BEGIN; + } +} + +static +int _check_mtime(GeoIP *gi) { + struct stat buf; + if (gi->flags & GEOIP_CHECK_CACHE) { + if (stat(gi->file_path, &buf) != -1) { + if (buf.st_mtime != gi->mtime) { + /* GeoIP Database file updated */ + if (gi->flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE)) { +#ifndef WIN32 + if ( gi->flags & GEOIP_MMAP_CACHE) { + munmap(gi->cache, gi->size); + gi->cache = NULL; + } else +#endif + { + /* reload database into memory cache */ + if ((gi->cache = (unsigned char*) realloc(gi->cache, buf.st_size)) == NULL) { + fprintf(stderr,"Out of memory when reloading %s\n",gi->file_path); + return -1; + } + } + } + /* refresh filehandle */ + fclose(gi->GeoIPDatabase); + gi->GeoIPDatabase = fopen(gi->file_path,"rb"); + if (gi->GeoIPDatabase == NULL) { + fprintf(stderr,"Error Opening file %s when reloading\n",gi->file_path); + return -1; + } + gi->mtime = buf.st_mtime; + gi->size = buf.st_size; + +#ifndef WIN32 + if ( gi->flags & GEOIP_MMAP_CACHE) { + gi->cache = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno(gi->GeoIPDatabase), 0); + if ( gi->cache == MAP_FAILED ) { + + fprintf(stderr,"Error remapping file %s when reloading\n",gi->file_path); + gi->cache = 0; + return -1; + } + } else +#endif + if ( gi->flags & GEOIP_MEMORY_CACHE ) { + if (fread(gi->cache, sizeof(unsigned char), buf.st_size, gi->GeoIPDatabase) != (size_t) buf.st_size) { + fprintf(stderr,"Error reading file %s when reloading\n",gi->file_path); + return -1; + } + } + if (gi->databaseSegments != NULL) { + free(gi->databaseSegments); + gi->databaseSegments = NULL; + } + _setup_segments(gi); + if (gi->databaseSegments == NULL) { + fprintf(stderr, "Error reading file %s -- corrupt\n", gi->file_path); + return -1; + } + if (gi->flags & GEOIP_INDEX_CACHE) { + gi->index_cache = (unsigned char *) realloc(gi->index_cache, sizeof(unsigned char) * ((gi->databaseSegments[0] * (long)gi->record_length * 2))); + if (gi->index_cache != NULL) { + fseek(gi->GeoIPDatabase, 0, SEEK_SET); + if (fread(gi->index_cache, sizeof(unsigned char), gi->databaseSegments[0] * (long)gi->record_length * 2, gi->GeoIPDatabase) != (size_t) (gi->databaseSegments[0]*(long)gi->record_length * 2)) { + fprintf(stderr,"Error reading file %s where reloading\n",gi->file_path); + return -1; + } + } + } + } + } + } + return 0; +} + +unsigned int _GeoIP_seek_record (GeoIP *gi, unsigned long ipnum) { + int depth; + unsigned int x; + unsigned char stack_buffer[2 * MAX_RECORD_LENGTH]; + const unsigned char *buf = (gi->cache == NULL) ? stack_buffer : NULL; + unsigned int offset = 0; + + const unsigned char * p; + int j; + + _check_mtime(gi); + for (depth = 31; depth >= 0; depth--) { + if (gi->cache == NULL && gi->index_cache == NULL) { + /* read from disk */ + fseek(gi->GeoIPDatabase, (long)gi->record_length * 2 * offset, SEEK_SET); + fread(stack_buffer,gi->record_length,2,gi->GeoIPDatabase); + } else if (gi->index_cache == NULL) { + /* simply point to record in memory */ + buf = gi->cache + (long)gi->record_length * 2 *offset; + } else { + buf = gi->index_cache + (long)gi->record_length * 2 * offset; + } + + if (ipnum & (1 << depth)) { + /* Take the right-hand branch */ + if ( gi->record_length == 3 ) { + /* Most common case is completely unrolled and uses constants. */ + x = (buf[3*1 + 0] << (0*8)) + + (buf[3*1 + 1] << (1*8)) + + (buf[3*1 + 2] << (2*8)); + + } else { + /* General case */ + j = gi->record_length; + p = &buf[2*j]; + x = 0; + do { + x <<= 8; + x += *(--p); + } while ( --j ); + } + + } else { + /* Take the left-hand branch */ + if ( gi->record_length == 3 ) { + /* Most common case is completely unrolled and uses constants. */ + x = (buf[3*0 + 0] << (0*8)) + + (buf[3*0 + 1] << (1*8)) + + (buf[3*0 + 2] << (2*8)); + } else { + /* General case */ + j = gi->record_length; + p = &buf[1*j]; + x = 0; + do { + x <<= 8; + x += *(--p); + } while ( --j ); + } + } + + if (x >= gi->databaseSegments[0]) { + gi->netmask = 32 - depth; + return x; + } + offset = x; + } + + /* shouldn't reach here */ + fprintf(stderr,"Error Traversing Database for ipnum = %lu - Perhaps database is corrupt?\n",ipnum); + return 0; +} + +unsigned long +_GeoIP_addr_to_num(const char *addr) +{ + unsigned int c, octet, t; + unsigned long ipnum; + int i = 3; + + octet = ipnum = 0; + while ((c = *addr++)) { + if (c == '.') { + if (octet > 255) + return 0; + ipnum <<= 8; + ipnum += octet; + i--; + octet = 0; + } else { + t = octet; + octet <<= 3; + octet += t; + octet += t; + c -= '0'; + if (c > 9) + return 0; + octet += c; + } + } + if ((octet > 255) || (i != 0)) + return 0; + ipnum <<= 8; + return ipnum + octet; +} +/* +GeoIP* GeoIP_open_type (int type, int flags) { + GeoIP * gi; + const char * filePath; + if (type < 0 || type >= NUM_DB_TYPES) { + printf("Invalid database type %d\n", type); + return NULL; + } + _GeoIP_setup_dbfilename(); + filePath = GeoIPDBFileName[type]; + if (filePath == NULL) { + printf("Invalid database type %d\n", type); + return NULL; + } + gi = GeoIP_open (filePath, flags); + return gi; +} + +GeoIP* GeoIP_new (int flags) { + GeoIP * gi; + _GeoIP_setup_dbfilename(); + gi = GeoIP_open (GeoIPDBFileName[GEOIP_COUNTRY_EDITION], flags); + return gi; +} +*/ +GeoIP* GeoIP_open (const char * filename, int flags) { + struct stat buf; + GeoIP * gi; + size_t len; + + gi = (GeoIP *)malloc(sizeof(GeoIP)); + if (gi == NULL) + return NULL; + len = sizeof(char) * (strlen(filename)+1); + gi->file_path = malloc(len); + if (gi->file_path == NULL) { + free(gi); + return NULL; + } + strncpy(gi->file_path, filename, len); + gi->GeoIPDatabase = fopen(filename,"rb"); + if (gi->GeoIPDatabase == NULL) { + fprintf(stderr,"Error Opening file %s\n",filename); + free(gi->file_path); + free(gi); + return NULL; + } else { + if (flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE) ) { + if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) { + fprintf(stderr,"Error stating file %s\n",filename); + free(gi->file_path); + free(gi); + return NULL; + } + gi->mtime = buf.st_mtime; + gi->size = buf.st_size; +#ifndef WIN32 + /* MMAP added my Peter Shipley */ + if ( flags & GEOIP_MMAP_CACHE) { + gi->cache = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno(gi->GeoIPDatabase), 0); + if ( gi->cache == MAP_FAILED ) { + fprintf(stderr,"Error mmaping file %s\n",filename); + free(gi->file_path); + free(gi); + return NULL; + } + } else +#endif + { + gi->cache = (unsigned char *) malloc(sizeof(unsigned char) * buf.st_size); + + if (gi->cache != NULL) { + if (fread(gi->cache, sizeof(unsigned char), buf.st_size, gi->GeoIPDatabase) != (size_t) buf.st_size) { + fprintf(stderr,"Error reading file %s\n",filename); + free(gi->cache); + free(gi->file_path); + free(gi); + return NULL; + } + } + } + } else { + if (flags & GEOIP_CHECK_CACHE) { + if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) { + fprintf(stderr,"Error stating file %s\n",filename); + free(gi->file_path); + free(gi); + return NULL; + } + gi->mtime = buf.st_mtime; + } + gi->cache = NULL; + } + gi->flags = flags; + gi->charset = GEOIP_CHARSET_ISO_8859_1; + + _setup_segments(gi); + if (flags & GEOIP_INDEX_CACHE) { + gi->index_cache = (unsigned char *) malloc(sizeof(unsigned char) * ((gi->databaseSegments[0] * (long)gi->record_length * 2))); + if (gi->index_cache != NULL) { + fseek(gi->GeoIPDatabase, 0, SEEK_SET); + if (fread(gi->index_cache, sizeof(unsigned char), gi->databaseSegments[0] * (long)gi->record_length * 2, gi->GeoIPDatabase) != (size_t) (gi->databaseSegments[0]*(long)gi->record_length * 2)) { + fprintf(stderr,"Error reading file %s\n",filename); + free(gi->databaseSegments); + free(gi->index_cache); + free(gi); + return NULL; + } + } + } else { + gi->index_cache = NULL; + } + return gi; + } +} + +void GeoIP_delete (GeoIP *gi) { + if (gi == NULL ) + return; + if (gi->GeoIPDatabase != NULL) + fclose(gi->GeoIPDatabase); + if (gi->cache != NULL) { +#ifndef WIN32 + if ( gi->flags & GEOIP_MMAP_CACHE) { + munmap(gi->cache, gi->size); + } else +#endif + { + free(gi->cache); + } + gi->cache = NULL; + } + if (gi->index_cache != NULL) + free(gi->index_cache); + if (gi->file_path != NULL) + free(gi->file_path); + if (gi->databaseSegments != NULL) + free(gi->databaseSegments); + free(gi); +} + +const char *GeoIP_country_code_by_name (GeoIP* gi, const char *name) { + int country_id; + country_id = GeoIP_id_by_name(gi, name); + return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; +} + +const char *GeoIP_country_code3_by_name (GeoIP* gi, const char *name) { + int country_id; + country_id = GeoIP_id_by_name(gi, name); + return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; +} + +const char *GeoIP_country_name_by_name (GeoIP* gi, const char *name) { + int country_id; + country_id = GeoIP_id_by_name(gi, name); + return (country_id > 0) ? GeoIP_country_name[country_id] : NULL; +} + +unsigned long _GeoIP_lookupaddress (const char *host) { + unsigned long addr = inet_addr(host); + struct hostent phe2; + struct hostent * phe = &phe2; + char *buf = NULL; + int buflength = 16384; + int herr = 0; + int result = 0; +#ifdef HAVE_GETHOSTBYNAME_R + buf = malloc(buflength); +#endif + if (addr == INADDR_NONE) { +#ifdef HAVE_GETHOSTBYNAME_R + while (1) { + /* we use gethostbyname_r here because it is thread-safe and gethostbyname is not */ +#ifdef GETHOSTBYNAME_R_RETURNS_INT + result = gethostbyname_r(host,&phe2,buf,buflength,&phe,&herr); +#else + phe = gethostbyname_r(host,&phe2,buf,buflength,&herr); +#endif + if (herr != ERANGE) + break; + if (result == 0) + break; + /* double the buffer if the buffer is too small */ + buflength = buflength * 2; + buf = realloc(buf,buflength); + } +#endif +#ifndef HAVE_GETHOSTBYNAME_R + /* Some systems do not support gethostbyname_r, such as Mac OS X */ + phe = gethostbyname(host); +#endif + if (!phe || result != 0) { + free(buf); + return 0; + } + addr = *((unsigned long *) phe->h_addr_list[0]); + } +#ifdef HAVE_GETHOSTBYNAME_R + free(buf); +#endif + return ntohl(addr); +} + +int GeoIP_id_by_name (GeoIP* gi, const char *name) { + unsigned long ipnum; + int ret; + if (name == NULL) { + return 0; + } + if (gi->databaseType != GEOIP_COUNTRY_EDITION && gi->databaseType != GEOIP_PROXY_EDITION && gi->databaseType != GEOIP_NETSPEED_EDITION) { + printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_COUNTRY_EDITION]); + return 0; + } + if (!(ipnum = _GeoIP_lookupaddress(name))) + return 0; + ret = _GeoIP_seek_record(gi, ipnum) - COUNTRY_BEGIN; + return ret; + +} + +const char *GeoIP_country_code_by_addr (GeoIP* gi, const char *addr) { + int country_id; + country_id = GeoIP_id_by_addr(gi, addr); + return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; +} + +const char *GeoIP_country_code3_by_addr (GeoIP* gi, const char *addr) { + int country_id; + country_id = GeoIP_id_by_addr(gi, addr); + return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; + return GeoIP_country_code3[country_id]; +} + +const char *GeoIP_country_name_by_addr (GeoIP* gi, const char *addr) { + int country_id; + country_id = GeoIP_id_by_addr(gi, addr); + return (country_id > 0) ? GeoIP_country_name[country_id] : NULL; + return GeoIP_country_name[country_id]; +} + +const char *GeoIP_country_name_by_ipnum (GeoIP* gi, unsigned long ipnum) { + int country_id; + country_id = GeoIP_id_by_ipnum(gi, ipnum); + return (country_id > 0) ? GeoIP_country_name[country_id] : NULL; +} + +const char *GeoIP_country_code_by_ipnum (GeoIP* gi, unsigned long ipnum) { + int country_id; + country_id = GeoIP_id_by_ipnum(gi, ipnum); + return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; +} + +const char *GeoIP_country_code3_by_ipnum (GeoIP* gi, unsigned long ipnum) { + int country_id; + country_id = GeoIP_id_by_ipnum(gi, ipnum); + return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; +} + +int GeoIP_country_id_by_addr (GeoIP* gi, const char *addr) { + return GeoIP_id_by_addr(gi, addr); +} + +int GeoIP_country_id_by_name (GeoIP* gi, const char *host) { + return GeoIP_id_by_name(gi, host); +} + +int GeoIP_id_by_addr (GeoIP* gi, const char *addr) { + unsigned long ipnum; + int ret; + if (addr == NULL) { + return 0; + } + if (gi->databaseType != GEOIP_COUNTRY_EDITION && + gi->databaseType != GEOIP_PROXY_EDITION && + gi->databaseType != GEOIP_NETSPEED_EDITION) { + printf("Invalid database type %s, expected %s\n", + GeoIPDBDescription[(int)gi->databaseType], + GeoIPDBDescription[GEOIP_COUNTRY_EDITION]); + return 0; + } + ipnum = _GeoIP_addr_to_num(addr); + ret = _GeoIP_seek_record(gi, ipnum) - COUNTRY_BEGIN; + return ret; +} + +int GeoIP_id_by_ipnum (GeoIP* gi, unsigned long ipnum) { + int ret; + if (ipnum == 0) { + return 0; + } + if (gi->databaseType != GEOIP_COUNTRY_EDITION && + gi->databaseType != GEOIP_PROXY_EDITION && + gi->databaseType != GEOIP_NETSPEED_EDITION) { + printf("Invalid database type %s, expected %s\n", + GeoIPDBDescription[(int)gi->databaseType], + GeoIPDBDescription[GEOIP_COUNTRY_EDITION]); + return 0; + } + ret = _GeoIP_seek_record(gi, ipnum) - COUNTRY_BEGIN; + return ret; +} + +char *GeoIP_database_info (GeoIP* gi) { + int i; + unsigned char buf[3]; + char *retval; + int hasStructureInfo = 0; + + if(gi == NULL) + return NULL; + + _check_mtime(gi); + fseek(gi->GeoIPDatabase, -3l, SEEK_END); + + /* first get past the database structure information */ + for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) { + fread(buf, 1, 3, gi->GeoIPDatabase); + if (buf[0] == 255 && buf[1] == 255 && buf[2] == 255) { + hasStructureInfo = 1; + break; + } + fseek(gi->GeoIPDatabase, -4l, SEEK_CUR); + } + if (hasStructureInfo == 1) { + fseek(gi->GeoIPDatabase, -6l, SEEK_CUR); + } else { + /* no structure info, must be pre Sep 2002 database, go back to end */ + fseek(gi->GeoIPDatabase, -3l, SEEK_END); + } + + for (i = 0; i < DATABASE_INFO_MAX_SIZE; i++) { + fread(buf, 1, 3, gi->GeoIPDatabase); + if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) { + retval = malloc(sizeof(char) * (i+1)); + if (retval == NULL) { + return NULL; + } + fread(retval, 1, i, gi->GeoIPDatabase); + retval[i] = '\0'; + return retval; + } + fseek(gi->GeoIPDatabase, -4l, SEEK_CUR); + } + return NULL; +} + +/* GeoIP Region Edition functions */ + +void GeoIP_assign_region_by_inetaddr(GeoIP* gi, unsigned long inetaddr, GeoIPRegion *region) { + unsigned int seek_region; + + /* This also writes in the terminating NULs (if you decide to + * keep them) and clear any fields that are not set. */ + memset(region, 0, sizeof(GeoIPRegion)); + + seek_region = _GeoIP_seek_record(gi, ntohl(inetaddr)); + + if (gi->databaseType == GEOIP_REGION_EDITION_REV0) { + /* Region Edition, pre June 2003 */ + seek_region -= STATE_BEGIN_REV0; + if (seek_region >= 1000) { + region->country_code[0] = 'U'; + region->country_code[1] = 'S'; + region->region[0] = (char) ((seek_region - 1000)/26 + 65); + region->region[1] = (char) ((seek_region - 1000)%26 + 65); + } else { + memcpy(region->country_code, GeoIP_country_code[seek_region], 2); + } + } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) { + /* Region Edition, post June 2003 */ + seek_region -= STATE_BEGIN_REV1; + if (seek_region < US_OFFSET) { + /* Unknown */ + /* we don't need to do anything here b/c we memset region to 0 */ + } else if (seek_region < CANADA_OFFSET) { + /* USA State */ + region->country_code[0] = 'U'; + region->country_code[1] = 'S'; + region->region[0] = (char) ((seek_region - US_OFFSET)/26 + 65); + region->region[1] = (char) ((seek_region - US_OFFSET)%26 + 65); + } else if (seek_region < WORLD_OFFSET) { + /* Canada Province */ + region->country_code[0] = 'C'; + region->country_code[1] = 'A'; + region->region[0] = (char) ((seek_region - CANADA_OFFSET)/26 + 65); + region->region[1] = (char) ((seek_region - CANADA_OFFSET)%26 + 65); + } else { + /* Not US or Canada */ + memcpy(region->country_code, GeoIP_country_code[(seek_region - WORLD_OFFSET) / FIPS_RANGE], 2); + } + } +} + +static +GeoIPRegion * _get_region(GeoIP* gi, unsigned long ipnum) { + GeoIPRegion * region; + + region = malloc(sizeof(GeoIPRegion)); + if (region) { + GeoIP_assign_region_by_inetaddr(gi, htonl(ipnum), region); + } + return region; +} + +GeoIPRegion * GeoIP_region_by_addr (GeoIP* gi, const char *addr) { + unsigned long ipnum; + if (addr == NULL) { + return 0; + } + if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && + gi->databaseType != GEOIP_REGION_EDITION_REV1) { + printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]); + return 0; + } + ipnum = _GeoIP_addr_to_num(addr); + return _get_region(gi, ipnum); +} + +GeoIPRegion * GeoIP_region_by_name (GeoIP* gi, const char *name) { + unsigned long ipnum; + if (name == NULL) { + return 0; + } + if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && + gi->databaseType != GEOIP_REGION_EDITION_REV1) { + printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]); + return 0; + } + if (!(ipnum = _GeoIP_lookupaddress(name))) + return 0; + return _get_region(gi, ipnum); +} + +GeoIPRegion * GeoIP_region_by_ipnum (GeoIP* gi, unsigned long ipnum) { + if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && + gi->databaseType != GEOIP_REGION_EDITION_REV1) { + printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]); + return 0; + } + return _get_region(gi, ipnum); +} + +void GeoIPRegion_delete (GeoIPRegion *gir) { + free(gir); +} + +/* GeoIP Organization, ISP and AS Number Edition private method */ +static +char *_get_name (GeoIP* gi, unsigned long ipnum) { + int seek_org; + char buf[MAX_ORG_RECORD_LENGTH]; + char * org_buf, * buf_pointer; + int record_pointer; + size_t len; + + if (gi->databaseType != GEOIP_ORG_EDITION && + gi->databaseType != GEOIP_ISP_EDITION && + gi->databaseType != GEOIP_ASNUM_EDITION) { + printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_ORG_EDITION]); + return 0; + } + + seek_org = _GeoIP_seek_record(gi, ipnum); + if (seek_org == gi->databaseSegments[0]) + return NULL; + + record_pointer = seek_org + (2 * gi->record_length - 1) * gi->databaseSegments[0]; + + if (gi->cache == NULL) { + fseek(gi->GeoIPDatabase, record_pointer, SEEK_SET); + fread(buf, sizeof(char), MAX_ORG_RECORD_LENGTH, gi->GeoIPDatabase); + len = sizeof(char) * (strlen(buf)+1); + org_buf = malloc(len); + strncpy(org_buf, buf, len); + } else { + buf_pointer = gi->cache + (long)record_pointer; + len = sizeof(char) * (strlen(buf_pointer)+1); + org_buf = malloc(len); + strncpy(org_buf, buf_pointer, len); + } + return org_buf; +} + +char *GeoIP_name_by_ipnum (GeoIP* gi, unsigned long ipnum) { + return _get_name(gi,ipnum); +} + +char *GeoIP_name_by_addr (GeoIP* gi, const char *addr) { + unsigned long ipnum; + if (addr == NULL) { + return 0; + } + ipnum = _GeoIP_addr_to_num(addr); + return _get_name(gi, ipnum); +} + +char *GeoIP_name_by_name (GeoIP* gi, const char *name) { + unsigned long ipnum; + if (name == NULL) { + return 0; + } + if (!(ipnum = _GeoIP_lookupaddress(name))) + return 0; + return _get_name(gi, ipnum); +} + +char *GeoIP_org_by_ipnum (GeoIP* gi, unsigned long ipnum) { + return GeoIP_name_by_ipnum(gi, ipnum); +} + +char *GeoIP_org_by_addr (GeoIP* gi, const char *addr) { + return GeoIP_name_by_addr(gi, addr); +} + +char *GeoIP_org_by_name (GeoIP* gi, const char *name) { + return GeoIP_name_by_name(gi, name); +} + +unsigned char GeoIP_database_edition (GeoIP* gi) { + return gi->databaseType; +} + +int GeoIP_charset( GeoIP* gi){ + return gi->charset; +} + +int GeoIP_set_charset( GeoIP* gi, int charset ){ + int old_charset = gi->charset; + gi->charset = charset; + return old_charset; +} + +int GeoIP_last_netmask (GeoIP* gi) { + return gi->netmask; +} + diff --git a/libtorrent/src/alert.cpp b/libtorrent/src/alert.cpp index be6f718ee..844cfb93b 100755 --- a/libtorrent/src/alert.cpp +++ b/libtorrent/src/alert.cpp @@ -35,38 +35,16 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/alert.hpp" #include +enum { queue_size_limit = 1000 }; + namespace libtorrent { - alert::alert(severity_t severity, const std::string& msg) - : m_msg(msg) - , m_severity(severity) - , m_timestamp(time_now()) - { - } - - alert::~alert() - { - } - - ptime alert::timestamp() const - { - return m_timestamp; - } - - const std::string& alert::msg() const - { - return m_msg; - } - - alert::severity_t alert::severity() const - { - return m_severity; - } - - + alert::alert() : m_timestamp(time_now()) {} + alert::~alert() {} + ptime alert::timestamp() const { return m_timestamp; } alert_manager::alert_manager() - : m_severity(alert::fatal) + : m_alert_mask(alert::error_notification) {} alert_manager::~alert_manager() @@ -105,15 +83,8 @@ namespace libtorrent { void alert_manager::post_alert(const alert& alert_) { boost::mutex::scoped_lock lock(m_mutex); - if (m_severity > alert_.severity()) return; - // the internal limit is 100 alerts - if (m_alerts.size() == 100) - { - alert* result = m_alerts.front(); - m_alerts.pop(); - delete result; - } + if (m_alerts.size() >= queue_size_limit) return; m_alerts.push(alert_.clone().release()); m_condition.notify_all(); } @@ -136,17 +107,5 @@ namespace libtorrent { return !m_alerts.empty(); } - void alert_manager::set_severity(alert::severity_t severity) - { - boost::mutex::scoped_lock lock(m_mutex); - - m_severity = severity; - } - - bool alert_manager::should_post(alert::severity_t severity) const - { - return severity >= m_severity; - } - } // namespace libtorrent diff --git a/libtorrent/src/allocate_resources.cpp b/libtorrent/src/allocate_resources.cpp deleted file mode 100644 index deef06dc4..000000000 --- a/libtorrent/src/allocate_resources.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - -Copyright (c) 2006, Magnus Jonsson, Arvid Norberg -All rights reserved. - -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. - -*/ - -//The Standard Library defines the two template functions std::min() -//and std::max() in the header. In general, you should -//use these template functions for calculating the min and max values -//of a pair. Unfortunately, Visual C++ does not define these function -// templates. This is because the names min and max clash with -//the traditional min and max macros defined in . -//As a workaround, Visual C++ defines two alternative templates with -//identical functionality called _cpp_min() and _cpp_max(). You can -//use them instead of std::min() and std::max().To disable the -//generation of the min and max macros in Visual C++, #define -//NOMINMAX before #including . - -#include "libtorrent/pch.hpp" - -#ifdef _WIN32 - //support boost1.32.0(2004-11-19 18:47) - //now all libs can be compiled and linked with static module - #define NOMINMAX -#endif - -#include "libtorrent/allocate_resources.hpp" -#include "libtorrent/size_type.hpp" -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/aux_/allocate_resources_impl.hpp" - -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1310 -#define for if (false) {} else for -#else -#include -#endif - -namespace libtorrent -{ - int saturated_add(int a, int b) - { - assert(a >= 0); - assert(b >= 0); - assert(a <= resource_request::inf); - assert(b <= resource_request::inf); - assert(resource_request::inf + resource_request::inf < 0); - - unsigned int sum = unsigned(a) + unsigned(b); - if (sum > unsigned(resource_request::inf)) - sum = resource_request::inf; - - assert(sum >= unsigned(a) && sum >= unsigned(b)); - return int(sum); - } - -#if defined(_MSC_VER) && _MSC_VER < 1310 - - namespace detail - { - struct iterator_wrapper - { - typedef std::map >::iterator orig_iter; - - orig_iter iter; - - iterator_wrapper(orig_iter i): iter(i) {} - void operator++() { ++iter; } - torrent& operator*() { return *(iter->second); } - bool operator==(const iterator_wrapper& i) const - { return iter == i.iter; } - bool operator!=(const iterator_wrapper& i) const - { return iter != i.iter; } - }; - - struct iterator_wrapper2 - { - typedef std::map::iterator orig_iter; - - orig_iter iter; - - iterator_wrapper2(orig_iter i): iter(i) {} - void operator++() { ++iter; } - peer_connection& operator*() { return *(iter->second); } - bool operator==(const iterator_wrapper2& i) const - { return iter == i.iter; } - bool operator!=(const iterator_wrapper2& i) const - { return iter != i.iter; } - }; - - } - - void allocate_resources( - int resources - , std::map >& c - , resource_request torrent::* res) - { - aux::allocate_resources_impl( - resources - , detail::iterator_wrapper(c.begin()) - , detail::iterator_wrapper(c.end()) - , res); - } - - void allocate_resources( - int resources - , std::map& c - , resource_request peer_connection::* res) - { - aux::allocate_resources_impl( - resources - , detail::iterator_wrapper2(c.begin()) - , detail::iterator_wrapper2(c.end()) - , res); - } - -#else - - namespace aux - { - peer_connection& pick_peer( - std::pair - , boost::intrusive_ptr > const& p) - { - return *p.second; - } - - peer_connection& pick_peer2( - std::pair const& p) - { - return *p.second; - } - - torrent& deref(std::pair > const& p) - { - return *p.second; - } - - session& deref(session* p) - { - return *p; - } - } - - void allocate_resources( - int resources - , std::map >& c - , resource_request torrent::* res) - { - typedef std::map >::iterator orig_iter; - typedef std::pair > in_param; - typedef boost::transform_iterator new_iter; - - aux::allocate_resources_impl( - resources - , new_iter(c.begin(), &aux::deref) - , new_iter(c.end(), &aux::deref) - , res); - } - - void allocate_resources( - int resources - , std::map& c - , resource_request peer_connection::* res) - { - typedef std::map::iterator orig_iter; - typedef std::pair in_param; - typedef boost::transform_iterator new_iter; - - aux::allocate_resources_impl( - resources - , new_iter(c.begin(), &aux::pick_peer2) - , new_iter(c.end(), &aux::pick_peer2) - , res); - } - - void allocate_resources( - int resources - , std::vector& _sessions - , resource_request session::* res) - { - typedef std::vector::iterator orig_iter; - typedef session* in_param; - typedef boost::transform_iterator new_iter; - - aux::allocate_resources_impl( - resources - , new_iter(_sessions.begin(), &aux::deref) - , new_iter(_sessions.end(), &aux::deref) - , res); - } - -#endif - -} // namespace libtorrent diff --git a/libtorrent/src/assert.cpp b/libtorrent/src/assert.cpp index 1073e05a3..2595b6114 100644 --- a/libtorrent/src/assert.cpp +++ b/libtorrent/src/assert.cpp @@ -30,6 +30,36 @@ POSSIBILITY OF SUCH DAMAGE. */ +#ifdef __GNUC__ + +#include +#include +#include +#include + +std::string demangle(char const* name) +{ +// in case this string comes + char const* start = strchr(name, '('); + if (start != 0) ++start; + else start = name; + char const* end = strchr(start, '+'); + + std::string in; + if (end == 0) in.assign(start); + else in.assign(start, end); + + size_t len; + int status; + char* unmangled = ::abi::__cxa_demangle(in.c_str(), 0, &len, &status); + if (unmangled == 0) return in; + std::string ret(unmangled); + free(unmangled); + return ret; +} + +#endif + #ifndef NDEBUG #include @@ -58,7 +88,7 @@ void assert_fail(char const* expr, int line, char const* file, char const* funct for (int i = 0; i < size; ++i) { - fprintf(stderr, "%d: %s\n", i, symbols[i]); + fprintf(stderr, "%d: %s\n", i, demangle(symbols[i]).c_str()); } free(symbols); diff --git a/libtorrent/src/broadcast_socket.cpp b/libtorrent/src/broadcast_socket.cpp index c7b7e71c8..cfb1a9f1a 100644 --- a/libtorrent/src/broadcast_socket.cpp +++ b/libtorrent/src/broadcast_socket.cpp @@ -30,8 +30,16 @@ POSSIBILITY OF SUCH DAMAGE. */ +#include + +#if BOOST_VERSION < 103500 #include #include +#else +#include +#include +#endif + #include #include "libtorrent/socket.hpp" @@ -75,10 +83,10 @@ namespace libtorrent return addr.to_v6() == address_v6::any(); } - address guess_local_address(asio::io_service& ios) + address guess_local_address(io_service& ios) { // make a best guess of the interface we're using and its IP - asio::error_code ec; + error_code ec; std::vector const& interfaces = enum_net_interfaces(ios, ec); address ret = address_v4::any(); for (std::vector::const_iterator i = interfaces.begin() @@ -137,7 +145,7 @@ namespace libtorrent - common_bits(b1.c_array(), b2.c_array(), b1.size()); } - broadcast_socket::broadcast_socket(asio::io_service& ios + broadcast_socket::broadcast_socket(io_service& ios , udp::endpoint const& multicast_endpoint , receive_handler_t const& handler , bool loopback) @@ -148,9 +156,14 @@ namespace libtorrent using namespace asio::ip::multicast; - asio::error_code ec; + error_code ec; std::vector interfaces = enum_net_interfaces(ios, ec); + if (multicast_endpoint.address().is_v4()) + open_multicast_socket(ios, address_v4::any(), loopback); + else + open_multicast_socket(ios, address_v6::any(), loopback); + for (std::vector::const_iterator i = interfaces.begin() , end(interfaces.end()); i != end; ++i) { @@ -161,58 +174,70 @@ namespace libtorrent // ignore any loopback interface if (is_loopback(i->interface_address)) continue; - boost::shared_ptr s(new datagram_socket(ios)); - if (i->interface_address.is_v4()) - { - s->open(udp::v4(), ec); - if (ec) continue; - s->set_option(datagram_socket::reuse_address(true), ec); - if (ec) continue; - s->bind(udp::endpoint(address_v4::any(), multicast_endpoint.port()), ec); - if (ec) continue; - s->set_option(join_group(multicast_endpoint.address()), ec); - if (ec) continue; - s->set_option(outbound_interface(i->interface_address.to_v4()), ec); - if (ec) continue; - } - else - { - s->open(udp::v6(), ec); - if (ec) continue; - s->set_option(datagram_socket::reuse_address(true), ec); - if (ec) continue; - s->bind(udp::endpoint(address_v6::any(), multicast_endpoint.port()), ec); - if (ec) continue; - s->set_option(join_group(multicast_endpoint.address()), ec); - if (ec) continue; -// s->set_option(outbound_interface(i->interface_address.to_v6()), ec); -// if (ec) continue; - } - s->set_option(hops(255), ec); - if (ec) continue; - s->set_option(enable_loopback(loopback), ec); - if (ec) continue; - m_sockets.push_back(socket_entry(s)); - socket_entry& se = m_sockets.back(); - s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer)) - , se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2)); #ifndef NDEBUG // std::cerr << "broadcast socket [ if: " << i->to_v4().to_string() // << " group: " << multicast_endpoint.address() << " ]" << std::endl; #endif + open_unicast_socket(ios, i->interface_address); } } - void broadcast_socket::send(char const* buffer, int size, asio::error_code& ec) + void broadcast_socket::open_multicast_socket(io_service& ios + , address const& addr, bool loopback) { - for (std::list::iterator i = m_sockets.begin() - , end(m_sockets.end()); i != end; ++i) + using namespace asio::ip::multicast; + + error_code ec; + boost::shared_ptr s(new datagram_socket(ios)); + if (addr.is_v4()) + s->open(udp::v4(), ec); + else + s->open(udp::v6(), ec); + if (ec) return; + s->set_option(datagram_socket::reuse_address(true), ec); + if (ec) return; + s->bind(udp::endpoint(addr, m_multicast_endpoint.port()), ec); + if (ec) return; + s->set_option(join_group(m_multicast_endpoint.address()), ec); + if (ec) return; + s->set_option(hops(255), ec); + if (ec) return; + s->set_option(enable_loopback(loopback), ec); + if (ec) return; + m_sockets.push_back(socket_entry(s)); + socket_entry& se = m_sockets.back(); + s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer)) + , se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2)); + } + + void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr) + { + using namespace asio::ip::multicast; + error_code ec; + boost::shared_ptr s(new datagram_socket(ios)); + s->open(addr.is_v4() ? udp::v4() : udp::v6(), ec); + if (ec) return; + s->bind(udp::endpoint(addr, 0), ec); + if (ec) return; + if (addr.is_v4()) + s->set_option(outbound_interface(addr.to_v4()), ec); + if (ec) return; + m_unicast_sockets.push_back(socket_entry(s)); + socket_entry& se = m_unicast_sockets.back(); + s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer)) + , se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2)); + } + + void broadcast_socket::send(char const* buffer, int size, error_code& ec) + { + for (std::list::iterator i = m_unicast_sockets.begin() + , end(m_unicast_sockets.end()); i != end; ++i) { if (!i->socket) continue; - asio::error_code e; + error_code e; i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e); #ifndef NDEBUG -// std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << std::endl; +// std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << " to: " << m_multicast_endpoint << std::endl; #endif if (e) { @@ -222,7 +247,7 @@ namespace libtorrent } } - void broadcast_socket::on_receive(socket_entry* s, asio::error_code const& ec + void broadcast_socket::on_receive(socket_entry* s, error_code const& ec , std::size_t bytes_transferred) { if (ec || bytes_transferred == 0 || !m_on_receive) return; @@ -234,14 +259,10 @@ namespace libtorrent void broadcast_socket::close() { - m_on_receive.clear(); + std::for_each(m_sockets.begin(), m_sockets.end(), bind(&socket_entry::close, _1)); + std::for_each(m_unicast_sockets.begin(), m_unicast_sockets.end(), bind(&socket_entry::close, _1)); - for (std::list::iterator i = m_sockets.begin() - , end(m_sockets.end()); i != end; ++i) - { - if (!i->socket) continue; - i->socket->close(); - } + m_on_receive.clear(); } } diff --git a/libtorrent/src/bt_peer_connection.cpp b/libtorrent/src/bt_peer_connection.cpp index ecce02ba2..dbba0e407 100755 --- a/libtorrent/src/bt_peer_connection.cpp +++ b/libtorrent/src/bt_peer_connection.cpp @@ -164,13 +164,19 @@ namespace libtorrent m_bandwidth_limit[upload_channel].assign(80); #endif +#ifndef NDEBUG + m_in_constructor = false; +#endif + } + + void bt_peer_connection::start() + { + peer_connection::start(); + // start in the state where we are trying to read the // handshake from the other side reset_recv_buffer(20); setup_receive(); -#ifndef NDEBUG - m_in_constructor = false; -#endif } bt_peer_connection::~bt_peer_connection() @@ -186,6 +192,7 @@ namespace libtorrent if (out_enc_policy == pe_settings::forced) { write_pe1_2_dhkey(); + if (is_disconnecting()) return; m_state = read_pe_dhkey; reset_recv_buffer(dh_key_len); @@ -208,6 +215,7 @@ namespace libtorrent fast_reconnect(true); write_pe1_2_dhkey(); + if (is_disconnecting()) return; m_state = read_pe_dhkey; reset_recv_buffer(dh_key_len); setup_receive(); @@ -239,7 +247,7 @@ namespace libtorrent { boost::shared_ptr t = associated_torrent().lock(); TORRENT_ASSERT(t); - write_bitfield(t->pieces()); + write_bitfield(); #ifndef TORRENT_DISABLE_DHT if (m_supports_dht_port && m_ses.m_dht) write_dht_port(m_ses.get_dht_settings().service_port); @@ -366,7 +374,7 @@ namespace libtorrent TORRENT_ASSERT(!m_encrypted); TORRENT_ASSERT(!m_rc4_encrypted); - TORRENT_ASSERT(!m_DH_key_exchange.get()); + TORRENT_ASSERT(!m_dh_key_exchange.get()); TORRENT_ASSERT(!m_sent_handshake); #ifdef TORRENT_VERBOSE_LOGGING @@ -374,7 +382,12 @@ namespace libtorrent (*m_logger) << " initiating encrypted handshake\n"; #endif - m_DH_key_exchange.reset(new DH_key_exchange); + m_dh_key_exchange.reset(new (std::nothrow) dh_key_exchange); + if (!m_dh_key_exchange || !m_dh_key_exchange->good()) + { + disconnect("out of memory"); + return; + } int pad_size = std::rand() % 512; @@ -383,10 +396,15 @@ namespace libtorrent #endif buffer::interval send_buf = allocate_send_buffer(dh_key_len + pad_size); + if (send_buf.begin == 0) + { + disconnect("out of memory"); + return; + } - std::copy(m_DH_key_exchange->get_local_key(), - m_DH_key_exchange->get_local_key() + dh_key_len, - send_buf.begin); + std::copy(m_dh_key_exchange->get_local_key(), + m_dh_key_exchange->get_local_key() + dh_key_len, + send_buf.begin); std::generate(send_buf.begin + dh_key_len, send_buf.end, std::rand); setup_send(); @@ -410,13 +428,14 @@ namespace libtorrent hasher h; sha1_hash const& info_hash = t->torrent_file().info_hash(); - char const* const secret = m_DH_key_exchange->get_secret(); + char const* const secret = m_dh_key_exchange->get_secret(); int pad_size = rand() % 512; // synchash,skeyhash,vc,crypto_provide,len(pad),pad,len(ia) buffer::interval send_buf = allocate_send_buffer(20 + 20 + 8 + 4 + 2 + pad_size + 2); + if (send_buf.begin == 0) return; // out of memory // sync hash (hash('req1',S)) h.reset(); @@ -444,7 +463,7 @@ namespace libtorrent // Discard DH key exchange data, setup RC4 keys init_pe_RC4_handler(secret, info_hash); - m_DH_key_exchange.reset(); // secret should be invalid at this point + m_dh_key_exchange.reset(); // secret should be invalid at this point // write the verification constant and crypto field TORRENT_ASSERT(send_buf.left() == 8 + 4 + 2 + pad_size + 2); @@ -491,6 +510,7 @@ namespace libtorrent const int buf_size = 8 + 4 + 2 + pad_size; buffer::interval send_buf = allocate_send_buffer(buf_size); + if (send_buf.begin == 0) return; // out of memory write_pe_vc_cryptofield(send_buf, crypto_select, pad_size); m_RC4_handler->encrypt(send_buf.end - buf_size, buf_size); @@ -581,7 +601,7 @@ namespace libtorrent #endif } - void bt_peer_connection::send_buffer(char* buf, int size) + void bt_peer_connection::send_buffer(char* buf, int size, int flags) { TORRENT_ASSERT(buf); TORRENT_ASSERT(size > 0); @@ -589,7 +609,7 @@ namespace libtorrent if (m_encrypted && m_rc4_encrypted) m_RC4_handler->encrypt(buf, size); - peer_connection::send_buffer(buf, size); + peer_connection::send_buffer(buf, size, flags); } buffer::interval bt_peer_connection::allocate_send_buffer(int size) @@ -683,6 +703,7 @@ namespace libtorrent const int string_len = sizeof(version_string)-1; buffer::interval i = allocate_send_buffer(1 + string_len + 8 + 20 + 20); + if (i.begin == 0) return; // out of memory // length of version string *i.begin = string_len; ++i.begin; @@ -790,18 +811,22 @@ namespace libtorrent TORRENT_ASSERT(received > 0); if (packet_size() != 1) - throw protocol_error("'choke' message size != 1"); + { + disconnect("'choke' message size != 1", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; incoming_choke(); + if (is_disconnecting()) return; if (!m_supports_fast) { boost::shared_ptr t = associated_torrent().lock(); TORRENT_ASSERT(t); while (!download_queue().empty()) { - piece_block const& b = download_queue().front(); + piece_block const& b = download_queue().front().block; peer_request r; r.piece = b.piece_index; r.start = b.block_index * t->block_size(); @@ -821,7 +846,10 @@ namespace libtorrent TORRENT_ASSERT(received > 0); if (packet_size() != 1) - throw protocol_error("'unchoke' message size != 1"); + { + disconnect("'unchoke' message size != 1", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; @@ -838,7 +866,10 @@ namespace libtorrent TORRENT_ASSERT(received > 0); if (packet_size() != 1) - throw protocol_error("'interested' message size != 1"); + { + disconnect("'interested' message size != 1", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; @@ -855,7 +886,10 @@ namespace libtorrent TORRENT_ASSERT(received > 0); if (packet_size() != 1) - throw protocol_error("'not interested' message size != 1"); + { + disconnect("'not interested' message size != 1", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; @@ -872,7 +906,10 @@ namespace libtorrent TORRENT_ASSERT(received > 0); if (packet_size() != 5) - throw protocol_error("'have' message size != 5"); + { + disconnect("'have' message size != 5", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; @@ -901,28 +938,21 @@ namespace libtorrent // verify the bitfield size if (t->valid_metadata() && packet_size() - 1 != ((int)get_bitfield().size() + 7) / 8) - throw protocol_error("bitfield with invalid size"); + { + disconnect("bitfield with invalid size", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; buffer::const_interval recv_buffer = receive_buffer(); - std::vector bitfield; + bitfield bits; + bits.borrow_bytes((char*)recv_buffer.begin + 1 + , t->valid_metadata()?get_bitfield().size():(packet_size()-1)*8); - if (!t->valid_metadata()) - bitfield.resize((packet_size() - 1) * 8); - else - bitfield.resize(get_bitfield().size()); - - // if we don't have metadata yet - // just remember the bitmask - // don't update the piecepicker - // (since it doesn't exist yet) - for (int i = 0; i < (int)bitfield.size(); ++i) - bitfield[i] = (recv_buffer[1 + (i>>3)] & (1 << (7 - (i&7)))) != 0; - - incoming_bitfield(bitfield); + incoming_bitfield(bits); } // ----------------------------- @@ -935,7 +965,10 @@ namespace libtorrent TORRENT_ASSERT(received > 0); if (packet_size() != 13) - throw protocol_error("'request' message size != 13"); + { + disconnect("'request' message size != 13", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; @@ -963,6 +996,14 @@ namespace libtorrent buffer::const_interval recv_buffer = receive_buffer(); int recv_pos = recv_buffer.end - recv_buffer.begin; + if (recv_pos == 1) + { + TORRENT_ASSERT(!has_disk_receive_buffer()); + if (!allocate_disk_receive_buffer(packet_size() - 9)) + return; + } + TORRENT_ASSERT(has_disk_receive_buffer()); + // classify the received data as protocol chatter // or data payload for the statistics if (recv_pos <= 9) @@ -983,6 +1024,7 @@ namespace libtorrent } incoming_piece_fragment(); + if (is_disconnecting()) return; if (!packet_finished()) return; const char* ptr = recv_buffer.begin + 1; @@ -991,7 +1033,8 @@ namespace libtorrent p.start = detail::read_int32(ptr); p.length = packet_size() - 9; - incoming_piece(p, recv_buffer.begin + 9); + disk_buffer_holder holder(m_ses, release_disk_receive_buffer()); + incoming_piece(p, holder); } // ----------------------------- @@ -1004,7 +1047,10 @@ namespace libtorrent TORRENT_ASSERT(received > 0); if (packet_size() != 13) - throw protocol_error("'cancel' message size != 13"); + { + disconnect("'cancel' message size != 13", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; @@ -1028,11 +1074,17 @@ namespace libtorrent INVARIANT_CHECK; if (!m_supports_dht_port) - throw protocol_error("got 'dht_port' message from peer that doesn't support it"); + { + disconnect("got 'dht_port' message from peer that doesn't support it", 2); + return; + } TORRENT_ASSERT(received > 0); if (packet_size() != 3) - throw protocol_error("'dht_port' message size != 3"); + { + disconnect("'dht_port' message size != 3", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; @@ -1049,7 +1101,10 @@ namespace libtorrent INVARIANT_CHECK; if (!m_supports_fast) - throw protocol_error("got 'suggest_piece' without FAST extension support"); + { + disconnect("got 'suggest_piece' without FAST excension support", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; @@ -1066,7 +1121,10 @@ namespace libtorrent INVARIANT_CHECK; if (!m_supports_fast) - throw protocol_error("got 'have_all' without FAST extension support"); + { + disconnect("got 'have_all' without FAST extension support", 2); + return; + } m_statistics.received_bytes(0, received); incoming_have_all(); } @@ -1076,7 +1134,10 @@ namespace libtorrent INVARIANT_CHECK; if (!m_supports_fast) - throw protocol_error("got 'have_none' without FAST extension support"); + { + disconnect("got 'have_none' without FAST extension support", 2); + return; + } m_statistics.received_bytes(0, received); incoming_have_none(); } @@ -1086,7 +1147,10 @@ namespace libtorrent INVARIANT_CHECK; if (!m_supports_fast) - throw protocol_error("got 'reject_request' without FAST extension support"); + { + disconnect("got 'reject_request' without FAST extension support", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; @@ -1107,7 +1171,10 @@ namespace libtorrent INVARIANT_CHECK; if (!m_supports_fast) - throw protocol_error("got 'allowed_fast' without FAST extension support"); + { + disconnect("got 'allowed_fast' without FAST extension support", 2); + return; + } m_statistics.received_bytes(0, received); if (!packet_finished()) return; @@ -1129,10 +1196,16 @@ namespace libtorrent TORRENT_ASSERT(received > 0); m_statistics.received_bytes(0, received); if (packet_size() < 2) - throw protocol_error("'extended' message smaller than 2 bytes"); + { + disconnect("'extended' message smaller than 2 bytes", 2); + return; + } if (associated_torrent().expired()) - throw protocol_error("'extended' message sent before proper handshake"); + { + disconnect("'extended' message sent before proper handshake", 2); + return; + } buffer::const_interval recv_buffer = receive_buffer(); if (recv_buffer.left() < 2) return; @@ -1158,8 +1231,10 @@ namespace libtorrent } #endif - throw protocol_error("unknown extended message id: " - + boost::lexical_cast(extended_id)); + std::stringstream msg; + msg << "unknown extended message id: " << extended_id; + disconnect(msg.str().c_str(), 2); + return; } void bt_peer_connection::on_extended_handshake() @@ -1171,29 +1246,23 @@ namespace libtorrent buffer::const_interval recv_buffer = receive_buffer(); - entry root; - try + lazy_entry root; + lazy_bdecode(recv_buffer.begin + 2, recv_buffer.end, root); + if (root.type() != lazy_entry::dict_t) { - root = bdecode(recv_buffer.begin + 2, recv_buffer.end); - } - catch (std::exception& exc) - { - (void)exc; #ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "invalid extended handshake: " << exc.what() << "\n"; + (*m_logger) << "invalid extended handshake\n"; #endif return; } #ifdef TORRENT_VERBOSE_LOGGING - std::stringstream ext; - root.print(ext); - (*m_logger) << "<== EXTENDED HANDSHAKE: \n" << ext.str(); + (*m_logger) << "<== EXTENDED HANDSHAKE: \n" << root; #endif #ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end;) + for (extension_list_t::iterator i = m_extensions.begin(); + !m_extensions.empty() && i != m_extensions.end();) { // a false return value means that the extension // isn't supported by the other end. So, it is removed. @@ -1205,52 +1274,46 @@ namespace libtorrent #endif // there is supposed to be a remote listen port - if (entry* listen_port = root.find_key("p")) + int listen_port = root.dict_find_int_value("p"); + if (listen_port > 0 && peer_info_struct() != 0) { - if (listen_port->type() == entry::int_t - && peer_info_struct() != 0) - { - t->get_policy().update_peer_port(int(listen_port->integer()) - , peer_info_struct(), peer_info::incoming); - } + t->get_policy().update_peer_port(listen_port + , peer_info_struct(), peer_info::incoming); } // there should be a version too // but where do we put that info? - if (entry* client_info = root.find_key("v")) - { - if (client_info->type() == entry::string_t) - m_client_version = client_info->string(); - } + std::string client_info = root.dict_find_string_value("v"); + if (!client_info.empty()) m_client_version = client_info; - if (entry* reqq = root.find_key("reqq")) - { - if (reqq->type() == entry::int_t) - m_max_out_request_queue = int(reqq->integer()); - if (m_max_out_request_queue < 1) - m_max_out_request_queue = 1; - } + int reqq = root.dict_find_int_value("reqq"); + if (reqq > 0) m_max_out_request_queue = reqq; - if (entry* myip = root.find_key("yourip")) + if (root.dict_find_int_value("upload_only")) + set_upload_only(true); + + std::string myip = root.dict_find_string_value("yourip"); + if (!myip.empty()) { // TODO: don't trust this blindly - if (myip->type() == entry::string_t) + if (myip.size() == address_v4::bytes_type::static_size) { - std::string const& my_ip = myip->string().c_str(); - if (my_ip.size() == address_v4::bytes_type::static_size) - { - address_v4::bytes_type bytes; - std::copy(my_ip.begin(), my_ip.end(), bytes.begin()); - m_ses.m_external_address = address_v4(bytes); - } - else if (my_ip.size() == address_v6::bytes_type::static_size) - { - address_v6::bytes_type bytes; - std::copy(my_ip.begin(), my_ip.end(), bytes.begin()); - m_ses.m_external_address = address_v6(bytes); - } + address_v4::bytes_type bytes; + std::copy(myip.begin(), myip.end(), bytes.begin()); + m_ses.set_external_address(address_v4(bytes)); + } + else if (myip.size() == address_v6::bytes_type::static_size) + { + address_v6::bytes_type bytes; + std::copy(myip.begin(), myip.end(), bytes.begin()); + m_ses.set_external_address(address_v6(bytes)); } } + + // if we're finished and this peer is uploading only + // disconnect it + if (t->is_finished() && upload_only()) + disconnect("upload to upload connection, closing"); } bool bt_peer_connection::dispatch_message(int received) @@ -1264,6 +1327,7 @@ namespace libtorrent buffer::const_interval recv_buffer = receive_buffer(); + TORRENT_ASSERT(recv_buffer.left() >= 1); int packet_type = recv_buffer[0]; if (packet_type < 0 || packet_type >= num_supported_messages @@ -1280,9 +1344,10 @@ namespace libtorrent } #endif - throw protocol_error("unknown message id: " - + boost::lexical_cast(packet_type) - + " size: " + boost::lexical_cast(packet_size())); + std::stringstream msg; + msg << "unkown message id: " << packet_type << " size: " << packet_size(); + disconnect(msg.str().c_str(), 2); + return packet_finished(); } TORRENT_ASSERT(m_message_handler[packet_type] != 0); @@ -1340,10 +1405,10 @@ namespace libtorrent detail::write_int32(r.piece, ptr); // index detail::write_int32(r.start, ptr); // begin detail::write_int32(r.length, ptr); // length - send_buffer(msg, sizeof(msg)); + send_buffer(msg, sizeof(msg), message_type_request); } - void bt_peer_connection::write_bitfield(std::vector const& bitfield) + void bt_peer_connection::write_bitfield() { INVARIANT_CHECK; @@ -1353,7 +1418,7 @@ namespace libtorrent TORRENT_ASSERT(t->valid_metadata()); // in this case, have_all or have_none should be sent instead - TORRENT_ASSERT(!m_supports_fast || !t->is_seed() || t->num_pieces() != 0); + TORRENT_ASSERT(!m_supports_fast || !t->is_seed() || t->num_have() != 0); if (m_supports_fast && t->is_seed()) { @@ -1361,19 +1426,26 @@ namespace libtorrent send_allowed_set(); return; } - else if (m_supports_fast && t->num_pieces() == 0) + else if (m_supports_fast && t->num_have() == 0) { write_have_none(); send_allowed_set(); return; } + else if (t->num_have() == 0) + { + // don't send a bitfield if we don't have any pieces +#ifndef NDEBUG + m_sent_bitfield = true; +#endif + return; + } - int num_pieces = bitfield.size(); + int num_pieces = t->torrent_file().num_pieces(); int lazy_pieces[50]; int num_lazy_pieces = 0; int lazy_piece = 0; - TORRENT_ASSERT(t->is_seed() == (std::count(bitfield.begin(), bitfield.end(), true) == num_pieces)); if (t->is_seed() && m_ses.settings().lazy_bitfields) { num_lazy_pieces = (std::min)(50, num_pieces / 10); @@ -1387,51 +1459,54 @@ namespace libtorrent lazy_piece = 0; } -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> BITFIELD "; - - std::stringstream bitfield_string; - for (int i = 0; i < (int)get_bitfield().size(); ++i) - { - if (lazy_piece < num_lazy_pieces - && lazy_pieces[lazy_piece] == i) - { - bitfield_string << "0"; - ++lazy_piece; - continue; - } - if (bitfield[i]) bitfield_string << "1"; - else bitfield_string << "0"; - } - bitfield_string << "\n"; - (*m_logger) << bitfield_string.str(); - lazy_piece = 0; -#endif const int packet_size = (num_pieces + 7) / 8 + 5; buffer::interval i = allocate_send_buffer(packet_size); + if (i.begin == 0) return; // out of memory detail::write_int32(packet_size - 4, i.begin); detail::write_uint8(msg_bitfield, i.begin); - std::fill(i.begin, i.end, 0); - for (int c = 0; c < num_pieces; ++c) + if (t->is_seed()) { - if (lazy_piece < num_lazy_pieces - && lazy_pieces[lazy_piece] == c) - { - ++lazy_piece; - continue; - } - if (bitfield[c]) - i.begin[c >> 3] |= 1 << (7 - (c & 7)); + memset(i.begin, 0xff, packet_size - 5); } + else + { + memset(i.begin, 0, packet_size - 5); + piece_picker const& p = t->picker(); + int mask = 0x80; + unsigned char* byte = (unsigned char*)i.begin; + for (int i = 0; i < num_pieces; ++i) + { + if (p.have_piece(i)) *byte |= mask; + mask >>= 1; + if (mask == 0) + { + mask = 0x80; + ++byte; + } + } + } + for (int c = 0; c < num_lazy_pieces; ++c) + i.begin[lazy_pieces[c] / 8] &= ~(0x80 >> (lazy_pieces[c] & 7)); TORRENT_ASSERT(i.end - i.begin == (num_pieces + 7) / 8); +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << time_now_string() << " ==> BITFIELD "; + + std::stringstream bitfield_string; + for (int k = 0; k < num_pieces; ++k) + { + if (i.begin[k / 8] & (0x80 >> (k % 8))) bitfield_string << "1"; + else bitfield_string << "0"; + } + bitfield_string << "\n"; + (*m_logger) << bitfield_string.str(); +#endif #ifndef NDEBUG m_sent_bitfield = true; #endif - setup_send(); if (num_lazy_pieces > 0) { @@ -1447,6 +1522,7 @@ namespace libtorrent if (m_supports_fast) send_allowed_set(); + setup_send(); } #ifndef TORRENT_DISABLE_EXTENSIONS @@ -1475,6 +1551,9 @@ namespace libtorrent detail::write_address(remote().address(), out); handshake["yourip"] = remote_address; handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue; + boost::shared_ptr t = associated_torrent().lock(); + TORRENT_ASSERT(t); + if (t->is_finished()) handshake["upload_only"] = 1; tcp::endpoint ep = m_ses.get_ipv6_interface(); if (ep != tcp::endpoint()) @@ -1498,6 +1577,7 @@ namespace libtorrent // make room for message buffer::interval i = allocate_send_buffer(6 + msg.size()); + if (i.begin == 0) return; // out of memory // write the length of the message detail::write_int32((int)msg.size() + 2, i.begin); @@ -1574,7 +1654,7 @@ namespace libtorrent send_buffer(msg, sizeof(msg)); } - void bt_peer_connection::write_piece(peer_request const& r, char* buffer) + void bt_peer_connection::write_piece(peer_request const& r, disk_buffer_holder& buffer) { INVARIANT_CHECK; @@ -1592,9 +1672,10 @@ namespace libtorrent detail::write_int32(r.start, ptr); send_buffer(msg, sizeof(msg)); - append_send_buffer(buffer, r.length + append_send_buffer(buffer.get(), r.length , boost::bind(&session_impl::free_disk_buffer , boost::ref(m_ses), _1)); + buffer.release(); m_payloads.push_back(range(send_buffer_size() - r.length, r.length)); setup_send(); @@ -1627,7 +1708,7 @@ namespace libtorrent // -------------------------- // throws exception when the client should be disconnected - void bt_peer_connection::on_receive(asio::error_code const& error + void bt_peer_connection::on_receive(error_code const& error , std::size_t bytes_transferred) { INVARIANT_CHECK; @@ -1642,8 +1723,9 @@ namespace libtorrent TORRENT_ASSERT(in_handshake() || !m_rc4_encrypted || m_encrypted); if (m_rc4_encrypted && m_encrypted) { - buffer::interval wr_buf = wr_recv_buffer(); - m_RC4_handler->decrypt((wr_buf.end - bytes_transferred), bytes_transferred); + std::pair wr_buf = wr_recv_buffers(bytes_transferred); + m_RC4_handler->decrypt(wr_buf.first.begin, wr_buf.first.left()); + if (wr_buf.second.left()) m_RC4_handler->decrypt(wr_buf.second.begin, wr_buf.second.left()); } #endif @@ -1655,20 +1737,24 @@ namespace libtorrent // for outgoing if (m_state == read_pe_dhkey) { - assert (!m_encrypted); - assert (!m_rc4_encrypted); - assert (packet_size() == dh_key_len); - assert (recv_buffer == receive_buffer()); + TORRENT_ASSERT(!m_encrypted); + TORRENT_ASSERT(!m_rc4_encrypted); + TORRENT_ASSERT(packet_size() == dh_key_len); + TORRENT_ASSERT(recv_buffer == receive_buffer()); if (!packet_finished()) return; - // write our dh public key. m_DH_key_exchange is + // write our dh public key. m_dh_key_exchange is // initialized in write_pe1_2_dhkey() - if (!is_local()) - write_pe1_2_dhkey(); + if (!is_local()) write_pe1_2_dhkey(); + if (is_disconnecting()) return; // read dh key, generate shared secret - m_DH_key_exchange->compute_secret (recv_buffer.begin); // TODO handle errors + if (m_dh_key_exchange->compute_secret(recv_buffer.begin) == -1) + { + disconnect("out of memory"); + return; + } #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << " received DH key\n"; @@ -1697,7 +1783,7 @@ namespace libtorrent // vc,crypto_select,len(pad),pad, encrypt(handshake) // 8+4+2+0+handshake_len - reset_recv_buffer(8+4+2+0+handshake_len); + reset_recv_buffer(8+4+2+0+handshake_len); } else { @@ -1721,10 +1807,7 @@ namespace libtorrent if (recv_buffer.left() < 20) { if (packet_finished()) - { - throw protocol_error ("sync hash not found"); - } - // else + disconnect("sync hash not found", 2); return; } @@ -1735,7 +1818,7 @@ namespace libtorrent // compute synchash (hash('req1',S)) h.update("req1", 4); - h.update(m_DH_key_exchange->get_secret(), dh_key_len); + h.update(m_dh_key_exchange->get_secret(), dh_key_len); m_sync_hash.reset(new sha1_hash(h.final())); } @@ -1749,7 +1832,10 @@ namespace libtorrent std::size_t bytes_processed = recv_buffer.left() - 20; m_sync_bytes_read += bytes_processed; if (m_sync_bytes_read >= 512) - throw protocol_error("sync hash not found within 532 bytes"); + { + disconnect("sync hash not found within 532 bytes", 2); + return; + } cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+20) - m_sync_bytes_read)); @@ -1805,7 +1891,7 @@ namespace libtorrent h.reset(); h.update("req3", 4); - h.update(m_DH_key_exchange->get_secret(), dh_key_len); + h.update(m_dh_key_exchange->get_secret(), dh_key_len); obfs_hash = h.final(); obfs_hash ^= skey_hash; @@ -1816,11 +1902,13 @@ namespace libtorrent if (!t) { attach_to_torrent(info_hash); + if (is_disconnecting()) return; + t = associated_torrent().lock(); TORRENT_ASSERT(t); } - init_pe_RC4_handler(m_DH_key_exchange->get_secret(), info_hash); + init_pe_RC4_handler(m_dh_key_exchange->get_secret(), info_hash); #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << " stream key found, torrent located.\n"; #endif @@ -1829,7 +1917,10 @@ namespace libtorrent } if (!m_RC4_handler.get()) - throw protocol_error("invalid streamkey identifier (info hash) in encrypted handshake"); + { + disconnect("invalid streamkey identifier (info hash) in encrypted handshake", 2); + return; + } // verify constant buffer::interval wr_recv_buf = wr_recv_buffer(); @@ -1839,7 +1930,8 @@ namespace libtorrent const char sh_vc[] = {0,0,0,0, 0,0,0,0}; if (!std::equal(sh_vc, sh_vc+8, recv_buffer.begin + 20)) { - throw protocol_error("unable to verify constant"); + disconnect("unable to verify constant", 2); + return; } #ifdef TORRENT_VERBOSE_LOGGING @@ -1860,10 +1952,7 @@ namespace libtorrent if (recv_buffer.left() < 8) { if (packet_finished()) - { - throw protocol_error ("sync verification constant not found"); - } - // else + disconnect("sync verification constant not found", 2); return; } @@ -1887,7 +1976,10 @@ namespace libtorrent std::size_t bytes_processed = recv_buffer.left() - 8; m_sync_bytes_read += bytes_processed; if (m_sync_bytes_read >= 512) - throw protocol_error("sync verification constant not found within 520 bytes"); + { + disconnect("sync verification constant not found within 520 bytes", 2); + return; + } cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+8) - m_sync_bytes_read)); @@ -1945,22 +2037,23 @@ namespace libtorrent // select a crypto method switch (m_ses.get_pe_settings().allowed_enc_level) { - case (pe_settings::plaintext): - { + case pe_settings::plaintext: if (!(crypto_field & 0x01)) - throw protocol_error("plaintext not provided"); + { + disconnect("plaintext not provided", 1); + return; + } crypto_select = 0x01; - } - break; - case (pe_settings::rc4): - { + break; + case pe_settings::rc4: if (!(crypto_field & 0x02)) - throw protocol_error("rc4 not provided"); + { + disconnect("rc4 not provided", 1); + return; + } crypto_select = 0x02; - } - break; - case (pe_settings::both): - { + break; + case pe_settings::both: if (m_ses.get_pe_settings().prefer_rc4) { if (crypto_field & 0x02) @@ -1976,8 +2069,11 @@ namespace libtorrent crypto_select = 0x02; } if (!crypto_select) - throw protocol_error("rc4/plaintext not provided"); - } + { + disconnect("rc4/plaintext not provided", 1); + return; + } + break; } // switch // write the pe4 step @@ -1991,22 +2087,34 @@ namespace libtorrent if (crypto_field == 0x02) { if (allowed_enc_level == pe_settings::plaintext) - throw protocol_error("rc4 selected by peer when not provided"); + { + disconnect("rc4 selected by peer when not provided", 2); + return; + } m_rc4_encrypted = true; } else if (crypto_field == 0x01) { if (allowed_enc_level == pe_settings::rc4) - throw protocol_error("plaintext selected by peer when not provided"); + { + disconnect("plaintext selected by peer when not provided", 2); + return; + } m_rc4_encrypted = false; } else - throw protocol_error("unsupported crypto method selected by peer"); + { + disconnect("unsupported crypto method selected by peer", 2); + return; + } } int len_pad = detail::read_int16(recv_buffer.begin); if (len_pad < 0 || len_pad > 512) - throw protocol_error("invalid pad length"); + { + disconnect("invalid pad length", 2); + return; + } m_state = read_pe_pad; if (!is_local()) @@ -2040,7 +2148,11 @@ namespace libtorrent recv_buffer.begin += pad_size; int len_ia = detail::read_int16(recv_buffer.begin); - if (len_ia < 0) throw protocol_error("invalid len_ia in handshake"); + if (len_ia < 0) + { + disconnect("invalid len_ia in handshake", 2); + return; + } #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << " len(IA) : " << len_ia << "\n"; @@ -2137,7 +2249,7 @@ namespace libtorrent if (m_state == read_protocol_identifier) { - assert (packet_size() == 20); + TORRENT_ASSERT(packet_size() == 20); if (!packet_finished()) return; recv_buffer = receive_buffer(); @@ -2150,7 +2262,10 @@ namespace libtorrent { #ifndef TORRENT_DISABLE_ENCRYPTION if (!is_local() && m_ses.get_pe_settings().in_enc_policy == pe_settings::disabled) - throw protocol_error("encrypted incoming connections disabled"); + { + disconnect("encrypted incoming connections disabled"); + return; + } // Don't attempt to perform an encrypted handshake // within an encrypted connection @@ -2165,18 +2280,22 @@ namespace libtorrent return; } - assert ((!is_local() && m_encrypted) || is_local()); + TORRENT_ASSERT((!is_local() && m_encrypted) || is_local()); #endif // #ifndef TORRENT_DISABLE_ENCRYPTION - throw protocol_error("incorrect protocol identifier"); + disconnect("incorrect protocol identifier", 2); + return; } #ifndef TORRENT_DISABLE_ENCRYPTION - assert (m_state != read_pe_dhkey); + TORRENT_ASSERT(m_state != read_pe_dhkey); if (!is_local() && (m_ses.get_pe_settings().in_enc_policy == pe_settings::forced) && !m_encrypted) - throw protocol_error("non encrypted incoming connections disabled"); + { + disconnect("non encrypted incoming connections disabled"); + return; + } #endif #ifdef TORRENT_VERBOSE_LOGGING @@ -2215,6 +2334,7 @@ namespace libtorrent #endif #ifndef DISABLE_EXTENSIONS + std::memcpy(m_reserved_bits, recv_buffer.begin, 20); if ((recv_buffer[5] & 0x10)) m_supports_extensions = true; #endif @@ -2235,6 +2355,7 @@ namespace libtorrent , (char*)info_hash.begin()); attach_to_torrent(info_hash); + if (is_disconnecting()) return; } else { @@ -2245,7 +2366,8 @@ namespace libtorrent #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << " received invalid info_hash\n"; #endif - throw protocol_error("invalid info-hash in handshake"); + disconnect("invalid info-hash in handshake", 2); + return; } #ifdef TORRENT_VERBOSE_LOGGING @@ -2260,7 +2382,9 @@ namespace libtorrent // sent the handshake if (!is_local()) write_handshake(); // if (t->valid_metadata()) -// write_bitfield(t->pieces()); +// write_bitfield(); + + if (is_disconnecting()) return; TORRENT_ASSERT(t->get_policy().has_connection(this)); @@ -2319,18 +2443,20 @@ namespace libtorrent // if not, we should close the outgoing one. if (pid < m_ses.get_peer_id() && is_local()) { - i->second.connection->disconnect(); + i->second.connection->disconnect("duplicate peer-id, connection closed"); } else { - throw protocol_error("duplicate peer-id, connection closed"); + disconnect("duplicate peer-id, connection closed"); + return; } } } if (pid == m_ses.get_peer_id()) { - throw protocol_error("closing connection to ourself"); + disconnect("closing connection to ourself", 1); + return; } m_client_version = identify_client(pid); @@ -2344,13 +2470,16 @@ namespace libtorrent // disconnect if the peer has the same peer-id as ourself // since it most likely is ourself then if (pid == m_ses.get_peer_id()) - throw std::runtime_error("closing connection to ourself"); + { + disconnect("closing connection to ourself", 1); + return; + } #ifndef TORRENT_DISABLE_EXTENSIONS for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end;) { - if (!(*i)->on_handshake()) + if (!(*i)->on_handshake(m_reserved_bits)) { i = m_extensions.erase(i); } @@ -2359,6 +2488,7 @@ namespace libtorrent ++i; } } + if (is_disconnecting()) return; if (m_supports_extensions) write_extensions(); #endif @@ -2383,10 +2513,10 @@ namespace libtorrent #endif m_state = read_packet_size; - reset_recv_buffer(4); + reset_recv_buffer(5); if (t->valid_metadata()) { - write_bitfield(t->pieces()); + write_bitfield(); #ifndef TORRENT_DISABLE_DHT if (m_supports_dht_port && m_ses.m_dht) write_dht_port(m_ses.get_dht_settings().service_port); @@ -2401,11 +2531,12 @@ namespace libtorrent if (m_state == read_packet_size) { // Make sure this is not fallen though into - assert (recv_buffer == receive_buffer()); + TORRENT_ASSERT(recv_buffer == receive_buffer()); if (!t) return; m_statistics.received_bytes(0, bytes_transferred); - if (!packet_finished()) return; + + if (recv_buffer.left() < 4) return; const char* ptr = recv_buffer.begin; int packet_size = detail::read_int32(ptr); @@ -2414,25 +2545,31 @@ namespace libtorrent if (packet_size > 1024*1024 || packet_size < 0) { // packet too large - throw std::runtime_error("packet > 1 MB (" - + boost::lexical_cast( - (unsigned int)packet_size) + " bytes)"); + std::stringstream msg; + msg << "packet > 1 MB (" << (unsigned int)packet_size << " bytes)"; + disconnect(msg.str().c_str(), 2); + return; } if (packet_size == 0) { incoming_keepalive(); + if (is_disconnecting()) return; // keepalive message m_state = read_packet_size; - reset_recv_buffer(4); + cut_receive_buffer(4, 4); + return; } else { + if (recv_buffer.left() < 5) return; + m_state = read_packet; - reset_recv_buffer(packet_size); + cut_receive_buffer(4, packet_size); + bytes_transferred = 1; + recv_buffer = receive_buffer(); + TORRENT_ASSERT(recv_buffer.left() == 1); } - TORRENT_ASSERT(!packet_finished()); - return; } if (m_state == read_packet) @@ -2442,7 +2579,7 @@ namespace libtorrent if (dispatch_message(bytes_transferred)) { m_state = read_packet_size; - reset_recv_buffer(4); + reset_recv_buffer(5); } TORRENT_ASSERT(!packet_finished()); return; @@ -2455,8 +2592,7 @@ namespace libtorrent // SEND DATA // -------------------------- - // throws exception when the client should be disconnected - void bt_peer_connection::on_sent(asio::error_code const& error + void bt_peer_connection::on_sent(error_code const& error , std::size_t bytes_transferred) { INVARIANT_CHECK; @@ -2501,7 +2637,7 @@ namespace libtorrent void bt_peer_connection::check_invariant() const { #ifndef TORRENT_DISABLE_ENCRYPTION - TORRENT_ASSERT( (bool(m_state != read_pe_dhkey) || m_DH_key_exchange.get()) + TORRENT_ASSERT( (bool(m_state != read_pe_dhkey) || m_dh_key_exchange.get()) || !is_local()); TORRENT_ASSERT(!m_rc4_encrypted || m_RC4_handler.get()); diff --git a/libtorrent/src/connection_queue.cpp b/libtorrent/src/connection_queue.cpp index a48456ed5..548fe07e6 100644 --- a/libtorrent/src/connection_queue.cpp +++ b/libtorrent/src/connection_queue.cpp @@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include "libtorrent/invariant_check.hpp" #include "libtorrent/connection_queue.hpp" +#include "libtorrent/socket.hpp" namespace libtorrent { @@ -45,25 +46,49 @@ namespace libtorrent #ifndef NDEBUG , m_in_timeout_function(false) #endif - {} + { +#ifdef TORRENT_CONNECTION_LOGGING + m_log.open("connection_queue.log"); +#endif + } - bool connection_queue::free_slots() const - { return m_num_connecting < m_half_open_limit || m_half_open_limit <= 0; } + int connection_queue::free_slots() const + { + mutex_t::scoped_lock l(m_mutex); + return m_half_open_limit == 0 ? (std::numeric_limits::max)() + : m_half_open_limit - m_queue.size(); + } void connection_queue::enqueue(boost::function const& on_connect , boost::function const& on_timeout - , time_duration timeout) + , time_duration timeout, int priority) { mutex_t::scoped_lock l(m_mutex); INVARIANT_CHECK; - m_queue.push_back(entry()); - entry& e = m_queue.back(); - e.on_connect = on_connect; - e.on_timeout = on_timeout; - e.ticket = m_next_ticket; - e.timeout = timeout; + TORRENT_ASSERT(priority >= 0); + TORRENT_ASSERT(priority < 2); + + entry* e = 0; + + switch (priority) + { + case 0: + m_queue.push_back(entry()); + e = &m_queue.back(); + break; + case 1: + m_queue.push_front(entry()); + e = &m_queue.front(); + break; + } + + e->priority = priority; + e->on_connect = on_connect; + e->on_timeout = on_timeout; + e->ticket = m_next_ticket; + e->timeout = timeout; ++m_next_ticket; try_connect(); } @@ -88,11 +113,15 @@ namespace libtorrent void connection_queue::close() { - m_timer.cancel(); + error_code ec; + m_timer.cancel(ec); } void connection_queue::limit(int limit) - { m_half_open_limit = limit; } + { + TORRENT_ASSERT(limit >= 0); + m_half_open_limit = limit; + } int connection_queue::limit() const { return m_half_open_limit; } @@ -116,12 +145,17 @@ namespace libtorrent { INVARIANT_CHECK; - if (!free_slots()) - return; +#ifdef TORRENT_CONNECTION_LOGGING + m_log << log_time() << " " << free_slots() << std::endl; +#endif + + if (m_num_connecting >= m_half_open_limit + && m_half_open_limit > 0) return; if (m_queue.empty()) { - m_timer.cancel(); + error_code ec; + m_timer.cancel(ec); return; } @@ -133,7 +167,8 @@ namespace libtorrent ptime expire = time_now() + i->timeout; if (m_num_connecting == 0) { - m_timer.expires_at(expire); + error_code ec; + m_timer.expires_at(expire, ec); m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1)); } i->connecting = true; @@ -144,9 +179,20 @@ namespace libtorrent entry& ent = *i; ++i; - try { ent.on_connect(ent.ticket); } catch (std::exception&) {} +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + ent.on_connect(ent.ticket); +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception&) {} +#endif - if (!free_slots()) break; +#ifdef TORRENT_CONNECTION_LOGGING + m_log << log_time() << " " << free_slots() << std::endl; +#endif + + if (m_num_connecting >= m_half_open_limit + && m_half_open_limit > 0) break; i = std::find_if(i, m_queue.end(), boost::bind(&entry::connecting, _1) == false); } } @@ -161,7 +207,7 @@ namespace libtorrent }; #endif - void connection_queue::on_timeout(asio::error_code const& e) + void connection_queue::on_timeout(error_code const& e) { mutex_t::scoped_lock l(m_mutex); @@ -206,7 +252,8 @@ namespace libtorrent if (next_expire < max_time()) { - m_timer.expires_at(next_expire); + error_code ec; + m_timer.expires_at(next_expire, ec); m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1)); } try_connect(); diff --git a/libtorrent/src/create_torrent.cpp b/libtorrent/src/create_torrent.cpp new file mode 100644 index 000000000..98f590d20 --- /dev/null +++ b/libtorrent/src/create_torrent.cpp @@ -0,0 +1,261 @@ +/* + +Copyright (c) 2008, Arvid Norberg +All rights reserved. + +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. + +*/ + +#include "libtorrent/create_torrent.hpp" +#include "libtorrent/file_pool.hpp" +#include "libtorrent/storage.hpp" + +#include +#include +#include + +namespace gr = boost::gregorian; + +namespace libtorrent +{ + create_torrent::create_torrent(file_storage& fs, int size) + : m_files(fs) + , m_creation_date(pt::second_clock::universal_time()) + , m_multifile(fs.num_files() > 1) + , m_private(false) + { + TORRENT_ASSERT(fs.num_files() > 0); + if (!m_multifile && m_files.at(0).path.has_branch_path()) m_multifile = true; + + // make sure the size is an even power of 2 +#ifndef NDEBUG + for (int i = 0; i < 32; ++i) + { + if (size & (1 << i)) + { + TORRENT_ASSERT((size & ~(1 << i)) == 0); + break; + } + } +#endif + m_files.set_piece_length(size); + m_files.set_num_pieces(static_cast( + (m_files.total_size() + m_files.piece_length() - 1) / m_files.piece_length())); + m_piece_hash.resize(m_files.num_pieces()); + } + + create_torrent::create_torrent(file_storage& fs) + : m_files(fs) + , m_creation_date(pt::second_clock::universal_time()) + , m_multifile(fs.num_files() > 1) + , m_private(false) + { + TORRENT_ASSERT(fs.num_files() > 0); + if (!m_multifile && m_files.at(0).path.has_branch_path()) m_multifile = true; + + const int target_size = 40 * 1024; + int size = fs.total_size() / (target_size / 20); + + for (int i = 4*1024*1024; i > 16*1024; i /= 2) + { + if (size < i) continue; + size = i; + break; + } + + m_files.set_piece_length(size); + m_files.set_num_pieces(static_cast( + (m_files.total_size() + m_files.piece_length() - 1) / m_files.piece_length())); + m_piece_hash.resize(m_files.num_pieces()); + } + entry create_torrent::generate() const + { + TORRENT_ASSERT(m_files.piece_length() > 0); + + if (m_files.num_files() == 0) + { + // TODO: throw something here + // throw + return entry(); + } + + entry dict; + + if (!m_urls.empty()) dict["announce"] = m_urls.front().first; + + if (!m_nodes.empty()) + { + entry& nodes = dict["nodes"]; + entry::list_type& nodes_list = nodes.list(); + for (nodes_t::const_iterator i = m_nodes.begin() + , end(m_nodes.end()); i != end; ++i) + { + entry::list_type node; + node.push_back(entry(i->first)); + node.push_back(entry(i->second)); + nodes_list.push_back(entry(node)); + } + } + + if (m_urls.size() > 1) + { + entry trackers(entry::list_t); + entry tier(entry::list_t); + int current_tier = m_urls.front().second; + for (std::vector::const_iterator i = m_urls.begin(); + i != m_urls.end(); ++i) + { + if (i->second != current_tier) + { + current_tier = i->second; + trackers.list().push_back(tier); + tier.list().clear(); + } + tier.list().push_back(entry(i->first)); + } + trackers.list().push_back(tier); + dict["announce-list"] = trackers; + } + + if (!m_comment.empty()) + dict["comment"] = m_comment; + + dict["creation date"] = + (m_creation_date - pt::ptime(gr::date(1970, gr::Jan, 1))).total_seconds(); + + if (!m_created_by.empty()) + dict["created by"] = m_created_by; + + if (!m_url_seeds.empty()) + { + if (m_url_seeds.size() == 1) + { + dict["url-list"] = m_url_seeds.front(); + } + else + { + entry& list = dict["url-list"]; + for (std::vector::const_iterator i + = m_url_seeds.begin(); i != m_url_seeds.end(); ++i) + { + list.list().push_back(entry(*i)); + } + } + } + + entry& info = dict["info"]; + info["name"] = m_files.name(); + + if (m_private) info["private"] = 1; + + if (!m_multifile) + { + info["length"] = m_files.at(0).size; + } + else + { + if (!info.find_key("files")) + { + entry& files = info["files"]; + + for (file_storage::iterator i = m_files.begin(); + i != m_files.end(); ++i) + { + files.list().push_back(entry()); + entry& file_e = files.list().back(); + file_e["length"] = i->size; + entry& path_e = file_e["path"]; + + TORRENT_ASSERT(i->path.has_branch_path()); + TORRENT_ASSERT(*i->path.begin() == m_files.name()); + + for (fs::path::iterator j = boost::next(i->path.begin()); + j != i->path.end(); ++j) + { + path_e.list().push_back(entry(*j)); + } + } + } + } + + info["piece length"] = m_files.piece_length(); + entry& pieces = info["pieces"]; + + std::string& p = pieces.string(); + + for (std::vector::const_iterator i = m_piece_hash.begin(); + i != m_piece_hash.end(); ++i) + { + p.append((char*)i->begin(), (char*)i->end()); + } + + std::vector buf; + bencode(std::back_inserter(buf), info); + m_info_hash = hasher(&buf[0], buf.size()).final(); + + return dict; + + } + + void create_torrent::add_tracker(std::string const& url, int tier) + { + m_urls.push_back(announce_entry(url, tier)); + + using boost::bind; + std::sort(m_urls.begin(), m_urls.end() + , bind(&announce_entry::second, _1) < bind(&announce_entry::second, _2)); + } + + void create_torrent::set_hash(int index, sha1_hash const& h) + { + TORRENT_ASSERT(index >= 0); + TORRENT_ASSERT(index < (int)m_piece_hash.size()); + m_piece_hash[index] = h; + } + + void create_torrent::add_node(std::pair const& node) + { + m_nodes.push_back(node); + } + + void create_torrent::add_url_seed(std::string const& url) + { + m_url_seeds.push_back(url); + } + + void create_torrent::set_comment(char const* str) + { + m_comment = str; + } + + void create_torrent::set_creator(char const* str) + { + m_created_by = str; + } + +} + diff --git a/libtorrent/include/libtorrent/kademlia/packet_iterator.hpp b/libtorrent/src/disk_buffer_holder.cpp similarity index 55% rename from libtorrent/include/libtorrent/kademlia/packet_iterator.hpp rename to libtorrent/src/disk_buffer_holder.cpp index e906a90bf..1ee83e93e 100644 --- a/libtorrent/include/libtorrent/kademlia/packet_iterator.hpp +++ b/libtorrent/src/disk_buffer_holder.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2006, Arvid Norberg +Copyright (c) 2008, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,66 +30,41 @@ POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PACKET_ITERATOR_HPP -#define PACKET_ITERATOR_HPP +#include "libtorrent/disk_buffer_holder.hpp" +#include "libtorrent/aux_/session_impl.hpp" +#include "libtorrent/disk_io_thread.hpp" -#include -#include -#include - -namespace libtorrent { namespace dht +namespace libtorrent { -class packet_iterator: public boost::iterator_facade< - packet_iterator, const char, boost::forward_traversal_tag> -{ -public: - typedef std::vector::const_iterator base_iterator; - - packet_iterator() {} - - packet_iterator(std::vector::const_iterator start - , std::vector::const_iterator end - , std::string const& error_msg = "") - : m_base(start) - , m_end(end) - , m_msg(error_msg) - {} - - base_iterator base() const - { return m_base; } - - base_iterator end() const - { return m_end; } - - int left() const { return int(m_end - m_base); } - -private: - friend class boost::iterator_core_access; - - bool equal(packet_iterator const& other) const - { return m_base == other.m_base; } - - void advance(int n) + disk_buffer_holder::disk_buffer_holder(aux::session_impl& ses, char* buf) + : m_iothread(ses.m_disk_thread), m_buf(buf) { - m_base += n; + TORRENT_ASSERT(buf == 0 || m_iothread.is_disk_buffer(buf)); } - void increment() - { ++m_base; } - - char const& dereference() const + disk_buffer_holder::disk_buffer_holder(disk_io_thread& iothread, char* buf) + : m_iothread(iothread), m_buf(buf) { - if (m_base == m_end) throw std::runtime_error(m_msg); - return *m_base; + TORRENT_ASSERT(buf == 0 || m_iothread.is_disk_buffer(buf)); } - base_iterator m_base; - base_iterator m_end; - std::string m_msg; -}; + void disk_buffer_holder::reset(char* buf) + { + if (m_buf) m_iothread.free_buffer(m_buf); + m_buf = buf; + } -} } // namespace libtorrent::dht + char* disk_buffer_holder::release() + { + char* ret = m_buf; + m_buf = 0; + return ret; + } -#endif // PACKET_ITERATOR_HPP + disk_buffer_holder::~disk_buffer_holder() + { + if (m_buf) m_iothread.free_buffer(m_buf); + } +} diff --git a/libtorrent/src/disk_io_thread.cpp b/libtorrent/src/disk_io_thread.cpp index f9a572348..adebdcf13 100644 --- a/libtorrent/src/disk_io_thread.cpp +++ b/libtorrent/src/disk_io_thread.cpp @@ -33,23 +33,34 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/storage.hpp" #include #include "libtorrent/disk_io_thread.hpp" +#include "libtorrent/disk_buffer_holder.hpp" +#include + +#ifdef _WIN32 +#include +#define alloca(s) _alloca(s) +#endif #ifdef TORRENT_DISK_STATS - #include "libtorrent/time.hpp" - #endif namespace libtorrent { - disk_io_thread::disk_io_thread(int block_size) + disk_io_thread::disk_io_thread(asio::io_service& ios, int block_size) : m_abort(false) , m_queue_buffer_size(0) + , m_cache_size(512) // 512 * 16kB = 8MB + , m_cache_expiry(60) // 1 minute + , m_coalesce_writes(true) + , m_coalesce_reads(true) + , m_use_read_cache(true) +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR , m_pool(block_size) -#ifndef NDEBUG - , m_block_size(block_size) #endif + , m_block_size(block_size) + , m_ios(ios) , m_disk_io_thread(boost::ref(*this)) { #ifdef TORRENT_STATS @@ -65,45 +76,63 @@ namespace libtorrent TORRENT_ASSERT(m_abort == true); } -#ifndef NDEBUG - disk_io_job disk_io_thread::find_job(boost::intrusive_ptr s - , int action, int piece) const - { - mutex_t::scoped_lock l(m_mutex); - for (std::list::const_iterator i = m_jobs.begin(); - i != m_jobs.end(); ++i) - { - if (i->storage != s) - continue; - if ((i->action == action || action == -1) && i->piece == piece) - return *i; - } - if ((m_current.action == action || action == -1) - && m_current.piece == piece) - return m_current; - - disk_io_job ret; - ret.action = (disk_io_job::action_t)-1; - ret.piece = -1; - return ret; - } - -#endif - void disk_io_thread::join() { - mutex_t::scoped_lock l(m_mutex); - m_abort = true; + mutex_t::scoped_lock l(m_queue_mutex); + disk_io_job j; + j.action = disk_io_job::abort_thread; + m_jobs.insert(m_jobs.begin(), j); m_signal.notify_all(); l.unlock(); m_disk_io_thread.join(); } + void disk_io_thread::get_cache_info(sha1_hash const& ih, std::vector& ret) const + { + mutex_t::scoped_lock l(m_piece_mutex); + ret.clear(); + ret.reserve(m_pieces.size()); + for (cache_t::const_iterator i = m_pieces.begin() + , end(m_pieces.end()); i != end; ++i) + { + torrent_info const& ti = *i->storage->info(); + if (ti.info_hash() != ih) continue; + cached_piece_info info; + info.piece = i->piece; + info.last_use = i->last_use; + int blocks_in_piece = (ti.piece_size(i->piece) + (m_block_size) - 1) / m_block_size; + info.blocks.resize(blocks_in_piece); + for (int b = 0; b < blocks_in_piece; ++b) + if (i->blocks[b]) info.blocks[b] = true; + ret.push_back(info); + } + } + + cache_status disk_io_thread::status() const + { + mutex_t::scoped_lock l(m_piece_mutex); + return m_cache_stats; + } + + void disk_io_thread::set_cache_size(int s) + { + mutex_t::scoped_lock l(m_piece_mutex); + TORRENT_ASSERT(s >= 0); + m_cache_size = s; + } + + void disk_io_thread::set_cache_expiry(int ex) + { + mutex_t::scoped_lock l(m_piece_mutex); + TORRENT_ASSERT(ex > 0); + m_cache_expiry = ex; + } + // aborts read operations void disk_io_thread::stop(boost::intrusive_ptr s) { - mutex_t::scoped_lock l(m_mutex); + mutex_t::scoped_lock l(m_queue_mutex); // read jobs are aborted, write and move jobs are syncronized for (std::list::iterator i = m_jobs.begin(); i != m_jobs.end();) @@ -115,7 +144,14 @@ namespace libtorrent } if (i->action == disk_io_job::read) { - i->callback(-1, *i); + if (i->callback) m_ios.post(bind(i->callback, -1, *i)); + m_jobs.erase(i++); + continue; + } + if (i->action == disk_io_job::check_files) + { + if (i->callback) m_ios.post(bind(i->callback + , piece_manager::disk_check_aborted, *i)); m_jobs.erase(i++); continue; } @@ -133,7 +169,7 @@ namespace libtorrent namespace { // The semantic of this operator is: - // shouls lhs come before rhs in the job queue + // should lhs come before rhs in the job queue bool operator<(disk_io_job const& lhs, disk_io_job const& rhs) { // NOTE: comparison inverted to make higher priority @@ -150,14 +186,450 @@ namespace libtorrent return false; } } + + disk_io_thread::cache_t::iterator disk_io_thread::find_cached_piece( + disk_io_thread::cache_t& cache + , disk_io_job const& j, mutex_t::scoped_lock& l) + { + for (cache_t::iterator i = cache.begin() + , end(cache.end()); i != end; ++i) + { + if (i->storage != j.storage || i->piece != j.piece) continue; + return i; + } + return cache.end(); + } + void disk_io_thread::flush_expired_pieces() + { + ptime now = time_now(); + + mutex_t::scoped_lock l(m_piece_mutex); + + INVARIANT_CHECK; + for (;;) + { + cache_t::iterator i = std::min_element( + m_pieces.begin(), m_pieces.end() + , bind(&cached_piece_entry::last_use, _1) + < bind(&cached_piece_entry::last_use, _2)); + if (i == m_pieces.end()) return; + int age = total_seconds(now - i->last_use); + if (age < m_cache_expiry) return; + flush_and_remove(i, l); + } + } + + void disk_io_thread::free_piece(cached_piece_entry& p, mutex_t::scoped_lock& l) + { + int piece_size = p.storage->info()->piece_size(p.piece); + int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; + + for (int i = 0; i < blocks_in_piece; ++i) + { + if (p.blocks[i] == 0) continue; + free_buffer(p.blocks[i]); + p.blocks[i] = 0; + --p.num_blocks; + --m_cache_stats.cache_size; + --m_cache_stats.read_cache_size; + } + } + + bool disk_io_thread::clear_oldest_read_piece( + cache_t::iterator ignore + , mutex_t::scoped_lock& l) + { + INVARIANT_CHECK; + + cache_t::iterator i = std::min_element( + m_read_pieces.begin(), m_read_pieces.end() + , bind(&cached_piece_entry::last_use, _1) + < bind(&cached_piece_entry::last_use, _2)); + if (i != m_read_pieces.end() && i != ignore) + { + // don't replace an entry that is less than one second old + if (time_now() - i->last_use < seconds(1)) return false; + free_piece(*i, l); + m_read_pieces.erase(i); + return true; + } + return false; + } + + void disk_io_thread::flush_oldest_piece(mutex_t::scoped_lock& l) + { + INVARIANT_CHECK; + // first look if there are any read cache entries that can + // be cleared + if (clear_oldest_read_piece(m_read_pieces.end(), l)) return; + + cache_t::iterator i = std::min_element( + m_pieces.begin(), m_pieces.end() + , bind(&cached_piece_entry::last_use, _1) + < bind(&cached_piece_entry::last_use, _2)); + if (i == m_pieces.end()) return; + flush_and_remove(i, l); + } + + void disk_io_thread::flush_and_remove(disk_io_thread::cache_t::iterator e + , mutex_t::scoped_lock& l) + { + flush(e, l); + m_pieces.erase(e); + } + + void disk_io_thread::flush(disk_io_thread::cache_t::iterator e + , mutex_t::scoped_lock& l) + { + INVARIANT_CHECK; + cached_piece_entry& p = *e; + int piece_size = p.storage->info()->piece_size(p.piece); +#ifdef TORRENT_DISK_STATS + m_log << log_time() << " flushing " << piece_size << std::endl; +#endif + TORRENT_ASSERT(piece_size > 0); + boost::scoped_array buf; + if (m_coalesce_writes) buf.reset(new (std::nothrow) char[piece_size]); + + int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; + int buffer_size = 0; + int offset = 0; + for (int i = 0; i <= blocks_in_piece; ++i) + { + if (i == blocks_in_piece || p.blocks[i] == 0) + { + if (buffer_size == 0) continue; + TORRENT_ASSERT(buf); + + TORRENT_ASSERT(buffer_size <= i * m_block_size); + l.unlock(); + p.storage->write_impl(buf.get(), p.piece, (std::min)( + i * m_block_size, piece_size) - buffer_size, buffer_size); + l.lock(); + ++m_cache_stats.writes; +// std::cerr << " flushing p: " << p.piece << " bytes: " << buffer_size << std::endl; + buffer_size = 0; + offset = 0; + continue; + } + int block_size = (std::min)(piece_size - i * m_block_size, m_block_size); + TORRENT_ASSERT(offset + block_size <= piece_size); + TORRENT_ASSERT(offset + block_size > 0); + if (!buf) + { + l.unlock(); + p.storage->write_impl(p.blocks[i], p.piece, i * m_block_size, block_size); + l.lock(); + ++m_cache_stats.writes; + } + else + { + std::memcpy(buf.get() + offset, p.blocks[i], block_size); + offset += m_block_size; + buffer_size += block_size; + } + free_buffer(p.blocks[i]); + p.blocks[i] = 0; + TORRENT_ASSERT(p.num_blocks > 0); + --p.num_blocks; + ++m_cache_stats.blocks_written; + --m_cache_stats.cache_size; + } + TORRENT_ASSERT(buffer_size == 0); +// std::cerr << " flushing p: " << p.piece << " cached_blocks: " << m_cache_stats.cache_size << std::endl; +#ifndef NDEBUG + for (int i = 0; i < blocks_in_piece; ++i) + TORRENT_ASSERT(p.blocks[i] == 0); +#endif + } + + void disk_io_thread::cache_block(disk_io_job& j, mutex_t::scoped_lock& l) + { + INVARIANT_CHECK; + TORRENT_ASSERT(find_cached_piece(m_pieces, j, l) == m_pieces.end()); + cached_piece_entry p; + + int piece_size = j.storage->info()->piece_size(j.piece); + int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; + + p.piece = j.piece; + p.storage = j.storage; + p.last_use = time_now(); + p.num_blocks = 1; + p.blocks.reset(new char*[blocks_in_piece]); + std::memset(&p.blocks[0], 0, blocks_in_piece * sizeof(char*)); + int block = j.offset / m_block_size; +// std::cerr << " adding cache entry for p: " << j.piece << " block: " << block << " cached_blocks: " << m_cache_stats.cache_size << std::endl; + p.blocks[block] = j.buffer; + ++m_cache_stats.cache_size; + m_pieces.push_back(p); + } + + // fills a piece with data from disk, returns the total number of bytes + // read or -1 if there was an error + int disk_io_thread::read_into_piece(cached_piece_entry& p, int start_block, mutex_t::scoped_lock& l) + { + int piece_size = p.storage->info()->piece_size(p.piece); + int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; + + int end_block = start_block; + for (int i = start_block; i < blocks_in_piece + && m_cache_stats.cache_size < m_cache_size; ++i) + { + // this is a block that is already allocated + // stop allocating and don't read more than + // what we've allocated now + if (p.blocks[i]) break; + p.blocks[i] = allocate_buffer(); + + // the allocation failed, break + if (p.blocks[i] == 0) break; + ++p.num_blocks; + ++m_cache_stats.cache_size; + ++m_cache_stats.read_cache_size; + ++end_block; + } + + if (end_block == start_block) return -2; + + int buffer_size = piece_size - (end_block - 1) * m_block_size + (end_block - start_block - 1) * m_block_size; + TORRENT_ASSERT(buffer_size <= piece_size); + TORRENT_ASSERT(buffer_size + start_block * m_block_size <= piece_size); + boost::scoped_array buf; + if (m_coalesce_reads) buf.reset(new (std::nothrow) char[buffer_size]); + int ret = 0; + if (buf) + { + l.unlock(); + ret += p.storage->read_impl(buf.get(), p.piece, start_block * m_block_size, buffer_size); + l.lock(); + if (!p.storage->error().empty()) { return -1; } + ++m_cache_stats.reads; + } + + int piece_offset = start_block * m_block_size; + int offset = 0; + for (int i = start_block; i < end_block; ++i) + { + int block_size = (std::min)(piece_size - piece_offset, m_block_size); + if (p.blocks[i] == 0) break; + TORRENT_ASSERT(offset <= buffer_size); + TORRENT_ASSERT(piece_offset <= piece_size); + if (buf) + { + std::memcpy(p.blocks[i], buf.get() + offset, block_size); + } + else + { + l.unlock(); + ret += p.storage->read_impl(p.blocks[i], p.piece, piece_offset, block_size); + if (!p.storage->error().empty()) { return -1; } + l.lock(); + ++m_cache_stats.reads; + } + offset += m_block_size; + piece_offset += m_block_size; + } + TORRENT_ASSERT(ret <= buffer_size); + return (ret != buffer_size) ? -1 : ret; + } + + bool disk_io_thread::make_room(int num_blocks + , cache_t::iterator ignore + , mutex_t::scoped_lock& l) + { + if (m_cache_size - m_cache_stats.cache_size < num_blocks) + { + // there's not enough room in the cache, clear a piece + // from the read cache + if (!clear_oldest_read_piece(ignore, l)) return false; + } + + return m_cache_size - m_cache_stats.cache_size >= num_blocks; + } + + // returns -1 on read error, -2 if there isn't any space in the cache + // or the number of bytes read + int disk_io_thread::cache_read_block(disk_io_job const& j, mutex_t::scoped_lock& l) + { + INVARIANT_CHECK; + + int piece_size = j.storage->info()->piece_size(j.piece); + int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; + + int start_block = j.offset / m_block_size; + + if (!make_room(blocks_in_piece - start_block + , m_read_pieces.end(), l)) return -2; + + cached_piece_entry p; + p.piece = j.piece; + p.storage = j.storage; + p.last_use = time_now(); + p.num_blocks = 0; + p.blocks.reset(new char*[blocks_in_piece]); + std::memset(&p.blocks[0], 0, blocks_in_piece * sizeof(char*)); + int ret = read_into_piece(p, start_block, l); + + if (ret == -1) + free_piece(p, l); + else + m_read_pieces.push_back(p); + + return ret; + } + +#ifndef NDEBUG + void disk_io_thread::check_invariant() const + { + int cached_write_blocks = 0; + for (cache_t::const_iterator i = m_pieces.begin() + , end(m_pieces.end()); i != end; ++i) + { + cached_piece_entry const& p = *i; + TORRENT_ASSERT(p.blocks); + + if (!p.storage) continue; + int piece_size = p.storage->info()->piece_size(p.piece); + int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; + int blocks = 0; + for (int k = 0; k < blocks_in_piece; ++k) + { + if (p.blocks[k]) + { +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR + TORRENT_ASSERT(is_disk_buffer(p.blocks[k])); +#endif + ++blocks; + } + } +// TORRENT_ASSERT(blocks == p.num_blocks); + cached_write_blocks += blocks; + } + + int cached_read_blocks = 0; + for (cache_t::const_iterator i = m_read_pieces.begin() + , end(m_read_pieces.end()); i != end; ++i) + { + cached_piece_entry const& p = *i; + TORRENT_ASSERT(p.blocks); + + int piece_size = p.storage->info()->piece_size(p.piece); + int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; + int blocks = 0; + for (int k = 0; k < blocks_in_piece; ++k) + { + if (p.blocks[k]) + { +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR + TORRENT_ASSERT(is_disk_buffer(p.blocks[k])); +#endif + ++blocks; + } + } +// TORRENT_ASSERT(blocks == p.num_blocks); + cached_read_blocks += blocks; + } + + TORRENT_ASSERT(cached_read_blocks + cached_write_blocks == m_cache_stats.cache_size); + TORRENT_ASSERT(cached_read_blocks == m_cache_stats.read_cache_size); + + // when writing, there may be a one block difference, right before an old piece + // is flushed + TORRENT_ASSERT(m_cache_stats.cache_size <= m_cache_size + 1); + } +#endif + + int disk_io_thread::try_read_from_cache(disk_io_job const& j) + { + TORRENT_ASSERT(j.buffer); + + mutex_t::scoped_lock l(m_piece_mutex); + if (!m_use_read_cache) return -2; + + cache_t::iterator p + = find_cached_piece(m_read_pieces, j, l); + + bool hit = true; + int ret = 0; + + // if the piece cannot be found in the cache, + // read the whole piece starting at the block + // we got a request for. + if (p == m_read_pieces.end()) + { + ret = cache_read_block(j, l); + hit = false; + if (ret < 0) return ret; + p = m_read_pieces.end(); + --p; + TORRENT_ASSERT(!m_read_pieces.empty()); + TORRENT_ASSERT(p->piece == j.piece); + TORRENT_ASSERT(p->storage == j.storage); + } + + if (p != m_read_pieces.end()) + { + // copy from the cache and update the last use timestamp + int block = j.offset / m_block_size; + int block_offset = j.offset % m_block_size; + int buffer_offset = 0; + int size = j.buffer_size; + if (p->blocks[block] == 0) + { + int piece_size = j.storage->info()->piece_size(j.piece); + int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; + int end_block = block; + while (end_block < blocks_in_piece && p->blocks[end_block] == 0) ++end_block; + if (!make_room(end_block - block, p, l)) return -2; + ret = read_into_piece(*p, block, l); + hit = false; + if (ret < 0) return ret; + TORRENT_ASSERT(p->blocks[block]); + } + + p->last_use = time_now(); + while (size > 0) + { + TORRENT_ASSERT(p->blocks[block]); + int to_copy = (std::min)(m_block_size + - block_offset, size); + std::memcpy(j.buffer + buffer_offset + , p->blocks[block] + block_offset + , to_copy); + size -= to_copy; + block_offset = 0; + buffer_offset += to_copy; + } + ret = j.buffer_size; + ++m_cache_stats.blocks_read; + if (hit) ++m_cache_stats.blocks_read_hit; + } + return ret; + } + void disk_io_thread::add_job(disk_io_job const& j , boost::function const& f) { TORRENT_ASSERT(!j.callback); TORRENT_ASSERT(j.storage); - mutex_t::scoped_lock l(m_mutex); - + TORRENT_ASSERT(j.buffer_size <= m_block_size); + mutex_t::scoped_lock l(m_queue_mutex); +#ifndef NDEBUG + if (j.action == disk_io_job::write) + { + cache_t::iterator p + = find_cached_piece(m_pieces, j, l); + if (p != m_pieces.end()) + { + int block = j.offset / m_block_size; + char const* buffer = p->blocks[block]; + TORRENT_ASSERT(buffer == 0); + } + } +#endif + std::list::reverse_iterator i = m_jobs.rbegin(); if (j.action == disk_io_job::read) { @@ -209,22 +681,42 @@ namespace libtorrent m_signal.notify_all(); } +#ifndef NDEBUG + bool disk_io_thread::is_disk_buffer(char* buffer) const + { +#ifdef TORRENT_DISABLE_POOL_ALLOCATOR + return true; +#else + mutex_t::scoped_lock l(m_pool_mutex); + return m_pool.is_from(buffer); +#endif + } +#endif + char* disk_io_thread::allocate_buffer() { - mutex_t::scoped_lock l(m_mutex); + mutex_t::scoped_lock l(m_pool_mutex); #ifdef TORRENT_STATS ++m_allocations; #endif +#ifdef TORRENT_DISABLE_POOL_ALLOCATOR + return (char*)malloc(m_block_size); +#else return (char*)m_pool.ordered_malloc(); +#endif } void disk_io_thread::free_buffer(char* buf) { - mutex_t::scoped_lock l(m_mutex); + mutex_t::scoped_lock l(m_pool_mutex); #ifdef TORRENT_STATS --m_allocations; #endif +#ifdef TORRENT_DISABLE_POOL_ALLOCATOR + free(buf); +#else m_pool.ordered_free(buf); +#endif } void disk_io_thread::operator()() @@ -234,125 +726,406 @@ namespace libtorrent #ifdef TORRENT_DISK_STATS m_log << log_time() << " idle" << std::endl; #endif - mutex_t::scoped_lock l(m_mutex); -#ifndef NDEBUG - m_current.action = (disk_io_job::action_t)-1; - m_current.piece = -1; -#endif + mutex_t::scoped_lock jl(m_queue_mutex); + while (m_jobs.empty() && !m_abort) - m_signal.wait(l); - if (m_abort && m_jobs.empty()) return; + m_signal.wait(jl); + if (m_abort && m_jobs.empty()) + { + jl.unlock(); + + mutex_t::scoped_lock l(m_piece_mutex); + // flush all disk caches + for (cache_t::iterator i = m_pieces.begin() + , end(m_pieces.end()); i != end; ++i) + flush(i, l); + for (cache_t::iterator i = m_read_pieces.begin() + , end(m_read_pieces.end()); i != end; ++i) + free_piece(*i, l); + m_pieces.clear(); + m_read_pieces.clear(); + return; + } + + // if there's a buffer in this job, it will be freed + // when this holder is destructed, unless it has been + // released. + disk_buffer_holder holder(*this + , m_jobs.front().action != disk_io_job::check_fastresume + ? m_jobs.front().buffer : 0); boost::function handler; handler.swap(m_jobs.front().callback); -#ifndef NDEBUG - m_current = m_jobs.front(); -#endif + disk_io_job j = m_jobs.front(); m_jobs.pop_front(); m_queue_buffer_size -= j.buffer_size; - l.unlock(); + jl.unlock(); + + flush_expired_pieces(); int ret = 0; - bool free_current_buffer = true; - try - { - TORRENT_ASSERT(j.storage); + TORRENT_ASSERT(j.storage || j.action == disk_io_job::abort_thread); #ifdef TORRENT_DISK_STATS - ptime start = time_now(); + ptime start = time_now(); #endif -// std::cerr << "DISK THREAD: executing job: " << j.action << std::endl; - switch (j.action) - { - case disk_io_job::read: -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " read " << j.buffer_size << std::endl; +#ifndef BOOST_NO_EXCEPTIONS + try { #endif - free_current_buffer = false; - if (j.buffer == 0) - { - j.buffer = allocate_buffer(); - TORRENT_ASSERT(j.buffer_size <= m_block_size); - if (j.buffer == 0) - { - ret = -1; - j.str = "out of memory"; - break; - } - } - ret = int(j.storage->read_impl(j.buffer, j.piece, j.offset - , j.buffer_size)); - // simulates slow drives - // usleep(300); - break; - case disk_io_job::write: -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " write " << j.buffer_size << std::endl; -#endif - TORRENT_ASSERT(j.buffer); - TORRENT_ASSERT(j.buffer_size <= m_block_size); - j.storage->write_impl(j.buffer, j.piece, j.offset - , j.buffer_size); - - // simulates a slow drive - // usleep(300); - break; - case disk_io_job::hash: + switch (j.action) + { + case disk_io_job::abort_thread: + { + mutex_t::scoped_lock jl(m_queue_mutex); + m_abort = true; + + for (std::list::iterator i = m_jobs.begin(); + i != m_jobs.end();) + { + if (i->action == disk_io_job::read) { -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " hash" << std::endl; -#endif - sha1_hash h = j.storage->hash_for_piece_impl(j.piece); - j.str.resize(20); - std::memcpy(&j.str[0], &h[0], 20); + if (i->callback) m_ios.post(bind(i->callback, -1, *i)); + m_jobs.erase(i++); + continue; } - break; - case disk_io_job::move_storage: -#ifdef TORRENT_DISK_STATS - m_log << log_time() << " move" << std::endl; + if (i->action == disk_io_job::check_files) + { + if (i->callback) m_ios.post(bind(i->callback + , piece_manager::disk_check_aborted, *i)); + m_jobs.erase(i++); + continue; + } + ++i; + } + break; + } + case disk_io_job::read: + { + std::string const& error_string = j.storage->error(); + if (!error_string.empty()) + { +#ifndef NDEBUG + std::cout << "ERROR: '" << error_string << "' " << j.error_file << std::endl; #endif - ret = j.storage->move_storage_impl(j.str) ? 1 : 0; - j.str = j.storage->save_path().string(); + j.str = error_string; + j.error_file = j.storage->error_file(); + j.storage->clear_error(); + ret = -1; break; - case disk_io_job::release_files: + } #ifdef TORRENT_DISK_STATS - m_log << log_time() << " release" << std::endl; + m_log << log_time() << " read " << j.buffer_size << std::endl; #endif - j.storage->release_files_impl(); + INVARIANT_CHECK; + TORRENT_ASSERT(j.buffer == 0); + j.buffer = allocate_buffer(); + TORRENT_ASSERT(j.buffer_size <= m_block_size); + if (j.buffer == 0) + { + ret = -1; + j.str = "out of memory"; break; - case disk_io_job::delete_files: + } + + disk_buffer_holder read_holder(*this, j.buffer); + ret = try_read_from_cache(j); + + // -2 means there's no space in the read cache + // or that the read cache is disabled + if (ret == -1) + { + j.buffer = 0; + j.str = j.storage->error(); + j.error_file = j.storage->error_file(); + j.storage->clear_error(); + break; + } + else if (ret == -2) + { + ret = j.storage->read_impl(j.buffer, j.piece, j.offset + , j.buffer_size); + if (ret < 0) + { + j.str = j.storage->error(); + j.error_file = j.storage->error_file(); + j.storage->clear_error(); + break; + } + ++m_cache_stats.blocks_read; + } + read_holder.release(); + break; + } + case disk_io_job::write: + { + std::string const& error_string = j.storage->error(); + if (!error_string.empty()) + { +#ifndef NDEBUG + std::cout << "ERROR: '" << error_string << "' " << j.error_file << std::endl; +#endif + j.str = error_string; + j.error_file = j.storage->error_file(); + j.storage->clear_error(); + ret = -1; + break; + } #ifdef TORRENT_DISK_STATS - m_log << log_time() << " delete" << std::endl; + m_log << log_time() << " write " << j.buffer_size << std::endl; #endif - j.storage->delete_files_impl(); + mutex_t::scoped_lock l(m_piece_mutex); + INVARIANT_CHECK; + cache_t::iterator p + = find_cached_piece(m_pieces, j, l); + int block = j.offset / m_block_size; + TORRENT_ASSERT(j.buffer); + TORRENT_ASSERT(j.buffer_size <= m_block_size); + if (p != m_pieces.end()) + { + TORRENT_ASSERT(p->blocks[block] == 0); + if (p->blocks[block]) + { + free_buffer(p->blocks[block]); + --p->num_blocks; + } + p->blocks[block] = j.buffer; + ++m_cache_stats.cache_size; + ++p->num_blocks; + p->last_use = time_now(); + } + else + { + cache_block(j, l); + } + // we've now inserted the buffer + // in the cache, we should not + // free it at the end + holder.release(); + if (m_cache_stats.cache_size >= m_cache_size) + flush_oldest_piece(l); + break; + } + case disk_io_job::hash: + { +#ifdef TORRENT_DISK_STATS + m_log << log_time() << " hash" << std::endl; +#endif + mutex_t::scoped_lock l(m_piece_mutex); + INVARIANT_CHECK; + + cache_t::iterator i + = find_cached_piece(m_pieces, j, l); + if (i != m_pieces.end()) + { + flush_and_remove(i, l); + std::string const& e = j.storage->error(); + if (!e.empty()) + { + j.str = e; + j.error_file = j.storage->error_file(); + ret = -1; + j.storage->clear_error(); + j.storage->mark_failed(j.piece); + break; + } + } + l.unlock(); + sha1_hash h = j.storage->hash_for_piece_impl(j.piece); + std::string const& e = j.storage->error(); + if (!e.empty()) + { + j.str = e; + j.error_file = j.storage->error_file(); + ret = -1; + j.storage->clear_error(); + j.storage->mark_failed(j.piece); break; + } + ret = (j.storage->info()->hash_for_piece(j.piece) == h)?0:-2; + if (ret == -2) j.storage->mark_failed(j.piece); + break; + } + case disk_io_job::move_storage: + { +#ifdef TORRENT_DISK_STATS + m_log << log_time() << " move" << std::endl; +#endif + TORRENT_ASSERT(j.buffer == 0); + ret = j.storage->move_storage_impl(j.str) ? 1 : 0; + if (ret != 0) + { + j.str = j.storage->error(); + j.error_file = j.storage->error_file(); + j.storage->clear_error(); + break; + } + j.str = j.storage->save_path().string(); + break; + } + case disk_io_job::release_files: + { +#ifdef TORRENT_DISK_STATS + m_log << log_time() << " release" << std::endl; +#endif + TORRENT_ASSERT(j.buffer == 0); + + mutex_t::scoped_lock l(m_piece_mutex); + INVARIANT_CHECK; + + for (cache_t::iterator i = m_pieces.begin(); i != m_pieces.end();) + { + if (i->storage == j.storage) + { + flush(i, l); + i = m_pieces.erase(i); + } + else + { + ++i; + } + } + l.unlock(); +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR + { + mutex_t::scoped_lock l(m_pool_mutex); + m_pool.release_memory(); + } +#endif + ret = j.storage->release_files_impl(); + if (ret != 0) + { + j.str = j.storage->error(); + j.error_file = j.storage->error_file(); + j.storage->clear_error(); + } + break; + } + case disk_io_job::delete_files: + { +#ifdef TORRENT_DISK_STATS + m_log << log_time() << " delete" << std::endl; +#endif + TORRENT_ASSERT(j.buffer == 0); + + mutex_t::scoped_lock l(m_piece_mutex); + INVARIANT_CHECK; + + cache_t::iterator i = std::remove_if( + m_pieces.begin(), m_pieces.end(), bind(&cached_piece_entry::storage, _1) == j.storage); + + for (cache_t::iterator k = i; k != m_pieces.end(); ++k) + { + torrent_info const& ti = *k->storage->info(); + int blocks_in_piece = (ti.piece_size(k->piece) + m_block_size - 1) / m_block_size; + for (int j = 0; j < blocks_in_piece; ++j) + { + if (k->blocks[j] == 0) continue; + free_buffer(k->blocks[j]); + k->blocks[j] = 0; + } + } + m_pieces.erase(i, m_pieces.end()); + l.unlock(); +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR + { + mutex_t::scoped_lock l(m_pool_mutex); + m_pool.release_memory(); + } +#endif + ret = j.storage->delete_files_impl(); + if (ret != 0) + { + j.str = j.storage->error(); + j.error_file = j.storage->error_file(); + j.storage->clear_error(); + } + break; + } + case disk_io_job::check_fastresume: + { +#ifdef TORRENT_DISK_STATS + m_log << log_time() << " check fastresume" << std::endl; +#endif + lazy_entry const* rd = (lazy_entry const*)j.buffer; + TORRENT_ASSERT(rd != 0); + ret = j.storage->check_fastresume(*rd, j.str); + break; + } + case disk_io_job::check_files: + { +#ifdef TORRENT_DISK_STATS + m_log << log_time() << " check files" << std::endl; +#endif + int piece_size = j.storage->info()->piece_length(); + for (int processed = 0; processed < 4 * 1024 * 1024; processed += piece_size) + { + ret = j.storage->check_files(j.piece, j.offset, j.str); + +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + TORRENT_ASSERT(handler); + if (handler && ret == piece_manager::need_full_check) + m_ios.post(bind(handler, ret, j)); +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception&) {} +#endif + if (ret != piece_manager::need_full_check) break; + } + // if the check is not done, add it at the end of the job queue + if (ret == piece_manager::need_full_check) + { + add_job(j, handler); + continue; + } + break; + } + case disk_io_job::save_resume_data: + { +#ifdef TORRENT_DISK_STATS + m_log << log_time() << " save resume data" << std::endl; +#endif + j.resume_data.reset(new entry(entry::dictionary_t)); + j.storage->write_resume_data(*j.resume_data); + ret = 0; + break; + } + case disk_io_job::rename_file: + { +#ifdef TORRENT_DISK_STATS + m_log << log_time() << " rename file" << std::endl; +#endif + ret = j.storage->rename_file_impl(j.piece, j.str); } } - catch (std::exception& e) +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception& e) { -// std::cerr << "DISK THREAD: exception: " << e.what() << std::endl; + ret = -1; try { j.str = e.what(); } catch (std::exception&) {} - ret = -1; } +#endif // if (!handler) std::cerr << "DISK THREAD: no callback specified" << std::endl; // else std::cerr << "DISK THREAD: invoking callback" << std::endl; - try { if (handler) handler(ret, j); } - catch (std::exception&) {} - -#ifndef NDEBUG - m_current.storage = 0; - m_current.callback.clear(); +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + if (handler) m_ios.post(bind(handler, ret, j)); +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception&) + { + TORRENT_ASSERT(false); + } #endif - - if (j.buffer && free_current_buffer) free_buffer(j.buffer); } + TORRENT_ASSERT(false); } } diff --git a/libtorrent/src/entry.cpp b/libtorrent/src/entry.cpp index 2688c491d..59e5b061d 100755 --- a/libtorrent/src/entry.cpp +++ b/libtorrent/src/entry.cpp @@ -35,8 +35,10 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "libtorrent/entry.hpp" #include "libtorrent/config.hpp" +#include "libtorrent/escape_string.hpp" #if defined(_MSC_VER) namespace std @@ -143,9 +145,38 @@ namespace libtorrent } #endif + entry::entry() + : m_type(undefined_t) + { +#ifndef NDEBUG + m_type_queried = true; +#endif + } + + entry::entry(data_type t) + : m_type(undefined_t) + { + construct(t); +#ifndef NDEBUG + m_type_queried = true; +#endif + } + + entry::entry(const entry& e) + : m_type(undefined_t) + { + copy(e); +#ifndef NDEBUG + m_type_queried = e.m_type_queried; +#endif + } + entry::entry(dictionary_type const& v) : m_type(undefined_t) { +#ifndef NDEBUG + m_type_queried = true; +#endif new(data) dictionary_type(v); m_type = dictionary_t; } @@ -153,6 +184,9 @@ namespace libtorrent entry::entry(string_type const& v) : m_type(undefined_t) { +#ifndef NDEBUG + m_type_queried = true; +#endif new(data) string_type(v); m_type = string_t; } @@ -160,6 +194,9 @@ namespace libtorrent entry::entry(list_type const& v) : m_type(undefined_t) { +#ifndef NDEBUG + m_type_queried = true; +#endif new(data) list_type(v); m_type = list_t; } @@ -167,6 +204,9 @@ namespace libtorrent entry::entry(integer_type const& v) : m_type(undefined_t) { +#ifndef NDEBUG + m_type_queried = true; +#endif new(data) integer_type(v); m_type = int_t; } @@ -176,6 +216,9 @@ namespace libtorrent destruct(); new(data) dictionary_type(v); m_type = dictionary_t; +#ifndef NDEBUG + m_type_queried = true; +#endif } void entry::operator=(string_type const& v) @@ -183,6 +226,9 @@ namespace libtorrent destruct(); new(data) string_type(v); m_type = string_t; +#ifndef NDEBUG + m_type_queried = true; +#endif } void entry::operator=(list_type const& v) @@ -190,6 +236,9 @@ namespace libtorrent destruct(); new(data) list_type(v); m_type = list_t; +#ifndef NDEBUG + m_type_queried = true; +#endif } void entry::operator=(integer_type const& v) @@ -197,6 +246,9 @@ namespace libtorrent destruct(); new(data) integer_type(v); m_type = int_t; +#ifndef NDEBUG + m_type_queried = true; +#endif } bool entry::operator==(entry const& e) const @@ -236,16 +288,17 @@ namespace libtorrent new (data) dictionary_type; break; default: - TORRENT_ASSERT(m_type == undefined_t); - m_type = undefined_t; - return; + TORRENT_ASSERT(t == undefined_t); } m_type = t; +#ifndef NDEBUG + m_type_queried = true; +#endif } void entry::copy(entry const& e) { - switch(e.m_type) + switch (e.type()) { case int_t: new(data) integer_type(e.integer()); @@ -260,10 +313,12 @@ namespace libtorrent new (data) dictionary_type(e.dict()); break; default: - m_type = undefined_t; - return; + TORRENT_ASSERT(e.type() == undefined_t); } - m_type = e.m_type; + m_type = e.type(); +#ifndef NDEBUG + m_type_queried = true; +#endif } void entry::destruct() @@ -287,6 +342,9 @@ namespace libtorrent break; } m_type = undefined_t; +#ifndef NDEBUG + m_type_queried = false; +#endif } void entry::swap(entry& e) @@ -315,21 +373,8 @@ namespace libtorrent break; } } - if (binary_string) - { - os.unsetf(std::ios_base::dec); - os.setf(std::ios_base::hex); - for (std::string::const_iterator i = string().begin(); i != string().end(); ++i) - os << std::setfill('0') << std::setw(2) - << static_cast((unsigned char)*i); - os.unsetf(std::ios_base::hex); - os.setf(std::ios_base::dec); - os << "\n"; - } - else - { - os << string() << "\n"; - } + if (binary_string) os << to_hex(string()) << "\n"; + else os << string() << "\n"; } break; case list_t: { @@ -344,8 +389,21 @@ namespace libtorrent os << "dictionary\n"; for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i) { + bool binary_string = false; + for (std::string::const_iterator k = i->first.begin(); k != i->first.end(); ++k) + { + if (!std::isprint(static_cast(*k))) + { + binary_string = true; + break; + } + } for (int j = 0; j < indent+1; ++j) os << " "; - os << "[" << i->first << "]"; + os << "["; + if (binary_string) os << to_hex(i->first); + else os << i->first; + os << "]"; + if (i->second.type() != entry::string_t && i->second.type() != entry::int_t) os << "\n"; diff --git a/libtorrent/src/enum_net.cpp b/libtorrent/src/enum_net.cpp index ec3238d52..eb5a9eeef 100644 --- a/libtorrent/src/enum_net.cpp +++ b/libtorrent/src/enum_net.cpp @@ -31,13 +31,27 @@ POSSIBILITY OF SUCH DAMAGE. */ #include "libtorrent/config.hpp" +#include +#include +#include "libtorrent/enum_net.hpp" +#include "libtorrent/broadcast_socket.hpp" +#if BOOST_VERSION < 103500 +#include +#else +#include +#endif -#if defined TORRENT_BSD || defined TORRENT_LINUX +#if defined TORRENT_BSD #include #include #include #include -#elif defined TORRENT_WINDOWS +#include +#include +#include +#endif + +#if defined TORRENT_WINDOWS #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif @@ -45,33 +59,161 @@ POSSIBILITY OF SUCH DAMAGE. #include #endif -#include "libtorrent/enum_net.hpp" -// for is_loopback and is_any -#include "libtorrent/broadcast_socket.hpp" +#if defined TORRENT_LINUX +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +namespace libtorrent { namespace +{ + + address inaddr_to_address(in_addr const* ina) + { + typedef asio::ip::address_v4::bytes_type bytes_t; + bytes_t b; + memcpy(&b[0], ina, b.size()); + return address_v4(b); + } + + address inaddr6_to_address(in6_addr const* ina6) + { + typedef asio::ip::address_v6::bytes_type bytes_t; + bytes_t b; + memcpy(&b[0], ina6, b.size()); + return address_v6(b); + } + + address sockaddr_to_address(sockaddr const* sin) + { + if (sin->sa_family == AF_INET) + return inaddr_to_address(&((sockaddr_in const*)sin)->sin_addr); + else if (sin->sa_family == AF_INET6) + return inaddr6_to_address(&((sockaddr_in6 const*)sin)->sin6_addr); + return address(); + } + +#if defined TORRENT_LINUX + + int read_nl_sock(int sock, char *buf, int bufsize, int seq, int pid) + { + nlmsghdr* nl_hdr; + + int msg_len = 0; + + do + { + int read_len = recv(sock, buf, bufsize - msg_len, 0); + if (read_len < 0) return -1; + + nl_hdr = (nlmsghdr*)buf; + + if ((NLMSG_OK(nl_hdr, read_len) == 0) || (nl_hdr->nlmsg_type == NLMSG_ERROR)) + return -1; + + if (nl_hdr->nlmsg_type == NLMSG_DONE) break; + + buf += read_len; + msg_len += read_len; + + if ((nl_hdr->nlmsg_flags & NLM_F_MULTI) == 0) break; + + } while((nl_hdr->nlmsg_seq != seq) || (nl_hdr->nlmsg_pid != pid)); + return msg_len; + } + + bool parse_route(nlmsghdr* nl_hdr, ip_route* rt_info) + { + rtmsg* rt_msg = (rtmsg*)NLMSG_DATA(nl_hdr); + + if((rt_msg->rtm_family != AF_INET) || (rt_msg->rtm_table != RT_TABLE_MAIN)) + return false; + + int rt_len = RTM_PAYLOAD(nl_hdr); + for (rtattr* rt_attr = (rtattr*)RTM_RTA(rt_msg); + RTA_OK(rt_attr,rt_len); rt_attr = RTA_NEXT(rt_attr,rt_len)) + { + switch(rt_attr->rta_type) + { + case RTA_OIF: + if_indextoname(*(int*)RTA_DATA(rt_attr), rt_info->name); + break; + case RTA_GATEWAY: + rt_info->gateway = address_v4(*(u_int*)RTA_DATA(rt_attr)); + break; + case RTA_DST: + rt_info->destination = address_v4(*(u_int*)RTA_DATA(rt_attr)); + break; + } + } + return true; + } +#endif + +#if defined TORRENT_BSD + + bool parse_route(rt_msghdr* rtm, ip_route* rt_info) + { + sockaddr* rti_info[RTAX_MAX]; + sockaddr* sa = (sockaddr*)(rtm + 1); + for (int i = 0; i < RTAX_MAX; ++i) + { + if ((rtm->rtm_addrs & (1 << i)) == 0) + { + rti_info[i] = 0; + continue; + } + rti_info[i] = sa; + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) + + sa = (sockaddr*)((char*)(sa) + ROUNDUP(sa->sa_len)); + +#undef ROUNDUP + } + + sa = rti_info[RTAX_GATEWAY]; + if (sa == 0 + || rti_info[RTAX_DST] == 0 + || rti_info[RTAX_NETMASK] == 0 + || (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)) + return false; + + rt_info->gateway = sockaddr_to_address(rti_info[RTAX_GATEWAY]); + rt_info->netmask = sockaddr_to_address(rti_info[RTAX_NETMASK]); + rt_info->destination = sockaddr_to_address(rti_info[RTAX_DST]); + if_indextoname(rtm->rtm_index, rt_info->name); + return true; + } +#endif + + +#ifdef TORRENT_BSD + bool verify_sockaddr(sockaddr_in* sin) + { + return (sin->sin_len == sizeof(sockaddr_in) + && sin->sin_family == AF_INET) + || (sin->sin_len == sizeof(sockaddr_in6) + && sin->sin_family == AF_INET6); + } +#endif + +}} // namespace libtorrent { - namespace - { - address sockaddr_to_address(sockaddr const* sin) - { - if (sin->sa_family == AF_INET) - { - typedef asio::ip::address_v4::bytes_type bytes_t; - bytes_t b; - memcpy(&b[0], &((sockaddr_in const*)sin)->sin_addr, b.size()); - return address_v4(b); - } - else if (sin->sa_family == AF_INET6) - { - typedef asio::ip::address_v6::bytes_type bytes_t; - bytes_t b; - memcpy(&b[0], &((sockaddr_in6 const*)sin)->sin6_addr, b.size()); - return address_v6(b); - } - return address(); - } - } bool in_subnet(address const& addr, ip_interface const& iface) { @@ -86,7 +228,7 @@ namespace libtorrent == (iface.interface_address.to_v4().to_ulong() & iface.netmask.to_v4().to_ulong()); } - bool in_local_network(asio::io_service& ios, address const& addr, asio::error_code& ec) + bool in_local_network(io_service& ios, address const& addr, error_code& ec) { std::vector const& net = enum_net_interfaces(ios, ec); if (ec) return false; @@ -98,10 +240,10 @@ namespace libtorrent return false; } - std::vector enum_net_interfaces(asio::io_service& ios, asio::error_code& ec) + std::vector enum_net_interfaces(io_service& ios, error_code& ec) { std::vector ret; - +// covers linux, MacOS X and BSD distributions #if defined TORRENT_LINUX || defined TORRENT_BSD int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) @@ -115,7 +257,7 @@ namespace libtorrent ifc.ifc_buf = buf; if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { - ec = asio::error_code(errno, asio::error::system_category); + ec = error_code(errno, asio::error::system_category); close(s); return ret; } @@ -132,6 +274,7 @@ namespace libtorrent { ip_interface iface; iface.interface_address = sockaddr_to_address(&item.ifr_addr); + strcpy(iface.name, item.ifr_name); ifreq netmask = item; if (ioctl(s, SIOCGIFNETMASK, &netmask) < 0) @@ -143,7 +286,7 @@ namespace libtorrent } else { - ec = asio::error_code(errno, asio::error::system_category); + ec = error_code(errno, asio::error::system_category); close(s); return ret; } @@ -170,7 +313,7 @@ namespace libtorrent SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); if (s == SOCKET_ERROR) { - ec = asio::error_code(WSAGetLastError(), asio::error::system_category); + ec = error_code(WSAGetLastError(), asio::error::system_category); return ret; } @@ -180,7 +323,7 @@ namespace libtorrent if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, 0, 0, buffer, sizeof(buffer), &size, 0, 0) != 0) { - ec = asio::error_code(WSAGetLastError(), asio::error::system_category); + ec = error_code(WSAGetLastError(), asio::error::system_category); closesocket(s); return ret; } @@ -193,6 +336,7 @@ namespace libtorrent { iface.interface_address = sockaddr_to_address(&buffer[i].iiAddress.Address); iface.netmask = sockaddr_to_address(&buffer[i].iiNetmask.Address); + iface.name[0] = 0; if (iface.interface_address == address_v4::any()) continue; ret.push_back(iface); } @@ -201,7 +345,7 @@ namespace libtorrent #warning THIS OS IS NOT RECOGNIZED, enum_net_interfaces WILL PROBABLY NOT WORK // make a best guess of the interface we're using and its IP udp::resolver r(ios); - udp::resolver::iterator i = r.resolve(udp::resolver::query(asio::ip::host_name(ec), "0")); + udp::resolver::iterator i = r.resolve(udp::resolver::query(asio::ip::host_name(ec), "0"), ec); if (ec) return ret; ip_interface iface; for (;i != udp::resolver_iterator(); ++i) @@ -215,16 +359,173 @@ namespace libtorrent return ret; } - address router_for_interface(address const interface, asio::error_code& ec) + address get_default_gateway(io_service& ios, error_code& ec) { + std::vector ret = enum_routes(ios, ec); #ifdef TORRENT_WINDOWS + std::vector::iterator i = std::find_if(ret.begin(), ret.end() + , boost::bind(&is_loopback, boost::bind(&ip_route::destination, _1))); +#else + std::vector::iterator i = std::find_if(ret.begin(), ret.end() + , boost::bind(&ip_route::destination, _1) == address()); +#endif + if (i == ret.end()) return address(); + return i->gateway; + } + + std::vector enum_routes(io_service& ios, error_code& ec) + { + std::vector ret; + +#if defined TORRENT_BSD +/* + struct rt_msg + { + rt_msghdr m_rtm; + char buf[512]; + }; + + rt_msg m; + int len = sizeof(rt_msg); + bzero(&m, len); + m.m_rtm.rtm_type = RTM_GET; + m.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY; + m.m_rtm.rtm_version = RTM_VERSION; + m.m_rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; + m.m_rtm.rtm_seq = 0; + m.m_rtm.rtm_msglen = len; + + int s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); + if (s == -1) + { + ec = error_code(errno, asio::error::system_category); + return std::vector(); + } + + int n = write(s, &m, len); + if (n == -1) + { + ec = error_code(errno, asio::error::system_category); + close(s); + return std::vector(); + } + else if (n != len) + { + ec = asio::error::operation_not_supported; + close(s); + return std::vector(); + } + bzero(&m, len); + + n = read(s, &m, len); + if (n == -1) + { + ec = error_code(errno, asio::error::system_category); + close(s); + return std::vector(); + } + + for (rt_msghdr* ptr = &m.m_rtm; (char*)ptr < ((char*)&m.m_rtm) + n; ptr = (rt_msghdr*)(((char*)ptr) + ptr->rtm_msglen)) + { + std::cout << " rtm_msglen: " << ptr->rtm_msglen << std::endl; + std::cout << " rtm_type: " << ptr->rtm_type << std::endl; + if (ptr->rtm_errno) + { + ec = error_code(ptr->rtm_errno, asio::error::system_category); + return std::vector(); + } + if (m.m_rtm.rtm_flags & RTF_UP == 0 + || m.m_rtm.rtm_flags & RTF_GATEWAY == 0) + { + ec = asio::error::operation_not_supported; + return address_v4::any(); + } + if (ptr->rtm_addrs & RTA_DST == 0 + || ptr->rtm_addrs & RTA_GATEWAY == 0 + || ptr->rtm_addrs & RTA_NETMASK == 0) + { + ec = asio::error::operation_not_supported; + return std::vector(); + } + if (ptr->rtm_msglen > len - ((char*)ptr - ((char*)&m.m_rtm))) + { + ec = asio::error::operation_not_supported; + return std::vector(); + } + int min_len = sizeof(rt_msghdr) + 2 * sizeof(sockaddr_in); + if (m.m_rtm.rtm_msglen < min_len) + { + ec = asio::error::operation_not_supported; + return std::vector(); + } + + ip_route r; + // destination + char* p = m.buf; + sockaddr_in* sin = (sockaddr_in*)p; + r.destination = sockaddr_to_address((sockaddr*)p); + + // gateway + p += sin->sin_len; + sin = (sockaddr_in*)p; + r.gateway = sockaddr_to_address((sockaddr*)p); + + // netmask + p += sin->sin_len; + sin = (sockaddr_in*)p; + r.netmask = sockaddr_to_address((sockaddr*)p); + ret.push_back(r); + } + close(s); +*/ + int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_DUMP, 0}; + + size_t needed = 0; + if (sysctl(mib, 6, 0, &needed, 0, 0) < 0) + { + ec = error_code(errno, asio::error::system_category); + return std::vector(); + } + + if (needed <= 0) + { + return std::vector(); + } + + boost::scoped_array buf(new (std::nothrow) char[needed]); + if (buf.get() == 0) + { + ec = asio::error::no_memory; + return std::vector(); + } + + if (sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0) + { + ec = error_code(errno, asio::error::system_category); + return std::vector(); + } + + char* end = buf.get() + needed; + + rt_msghdr* rtm; + for (char* next = buf.get(); next < end; next += rtm->rtm_msglen) + { + rtm = (rt_msghdr*)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + + ip_route r; + if (parse_route(rtm, &r)) ret.push_back(r); + } + +#elif defined TORRENT_WINDOWS // Load Iphlpapi library HMODULE iphlp = LoadLibraryA("Iphlpapi.dll"); if (!iphlp) { - ec = asio::error::fault; - return address_v4::any(); + ec = asio::error::operation_not_supported; + return std::vector(); } // Get GetAdaptersInfo() pointer @@ -233,8 +534,8 @@ namespace libtorrent if (!GetAdaptersInfo) { FreeLibrary(iphlp); - ec = asio::error::fault; - return address_v4::any(); + ec = asio::error::operation_not_supported; + return std::vector(); } PIP_ADAPTER_INFO adapter_info = 0; @@ -242,37 +543,36 @@ namespace libtorrent if (GetAdaptersInfo(adapter_info, &out_buf_size) != ERROR_BUFFER_OVERFLOW) { FreeLibrary(iphlp); - ec = asio::error::fault; - return address_v4::any(); + ec = asio::error::operation_not_supported; + return std::vector(); } adapter_info = (IP_ADAPTER_INFO*)malloc(out_buf_size); if (!adapter_info) { FreeLibrary(iphlp); - ec = asio::error::fault; - return address_v4::any(); + ec = asio::error::no_memory; + return std::vector(); } - address ret; if (GetAdaptersInfo(adapter_info, &out_buf_size) == NO_ERROR) { - for (PIP_ADAPTER_INFO adapter = adapter_info; adapter != 0; adapter = adapter->Next) { - address iface = address::from_string(adapter->IpAddressList.IpAddress.String, ec); + + ip_route r; + r.destination = address::from_string(adapter->IpAddressList.IpAddress.String, ec); + r.gateway = address::from_string(adapter->GatewayList.IpAddress.String, ec); + r.netmask = address::from_string(adapter->IpAddressList.IpMask.String, ec); + strncpy(r.name, adapter->AdapterName, sizeof(r.name)); + if (ec) { - ec = asio::error_code(); + ec = error_code(); continue; } - if (is_loopback(iface) || is_any(iface)) continue; - if (interface == address() || interface == iface) - { - ret = address::from_string(adapter->GatewayList.IpAddress.String, ec); - break; - } + ret.push_back(r); } } @@ -280,17 +580,53 @@ namespace libtorrent free(adapter_info); FreeLibrary(iphlp); - return ret; +#elif defined TORRENT_LINUX -#else - // TODO: temporary implementation - if (!interface.is_v4()) + enum { BUFSIZE = 8192 }; + + int sock = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE); + if (sock < 0) { - ec = asio::error::fault; - return address_v4::any(); + ec = error_code(errno, asio::error::system_category); + return std::vector(); } - return address_v4((interface.to_v4().to_ulong() & 0xffffff00) | 1); + + int seq = 0; + + char msg[BUFSIZE]; + memset(msg, 0, BUFSIZE); + nlmsghdr* nl_msg = (nlmsghdr*)msg; + + nl_msg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg)); + nl_msg->nlmsg_type = RTM_GETROUTE; + nl_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; + nl_msg->nlmsg_seq = seq++; + nl_msg->nlmsg_pid = getpid(); + + if (send(sock, nl_msg, nl_msg->nlmsg_len, 0) < 0) + { + ec = error_code(errno, asio::error::system_category); + close(sock); + return std::vector(); + } + + int len = read_nl_sock(sock, msg, BUFSIZE, seq, getpid()); + if (len < 0) + { + ec = error_code(errno, asio::error::system_category); + close(sock); + return std::vector(); + } + + for (; NLMSG_OK(nl_msg, len); nl_msg = NLMSG_NEXT(nl_msg, len)) + { + ip_route r; + if (parse_route(nl_msg, &r)) ret.push_back(r); + } + close(sock); + #endif + return ret; } } diff --git a/libtorrent/src/escape_string.cpp b/libtorrent/src/escape_string.cpp index 323a3e12b..616570014 100755 --- a/libtorrent/src/escape_string.cpp +++ b/libtorrent/src/escape_string.cpp @@ -38,6 +38,9 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include + +#include #include "libtorrent/assert.hpp" @@ -60,23 +63,41 @@ namespace libtorrent { ++i; if (i == s.end()) +#ifdef BOOST_NO_EXCEPTIONS + return ret; +#else throw std::runtime_error("invalid escaped string"); +#endif int high; if(*i >= '0' && *i <= '9') high = *i - '0'; else if(*i >= 'A' && *i <= 'F') high = *i + 10 - 'A'; else if(*i >= 'a' && *i <= 'f') high = *i + 10 - 'a'; - else throw std::runtime_error("invalid escaped string"); + else +#ifdef BOOST_NO_EXCEPTIONS + return ret; +#else + throw std::runtime_error("invalid escaped string"); +#endif ++i; if (i == s.end()) +#ifdef BOOST_NO_EXCEPTIONS + return ret; +#else throw std::runtime_error("invalid escaped string"); +#endif int low; if(*i >= '0' && *i <= '9') low = *i - '0'; else if(*i >= 'A' && *i <= 'F') low = *i + 10 - 'A'; else if(*i >= 'a' && *i <= 'f') low = *i + 10 - 'a'; - else throw std::runtime_error("invalid escaped string"); + else +#ifdef BOOST_NO_EXCEPTIONS + return ret; +#else + throw std::runtime_error("invalid escaped string"); +#endif ret += char(high * 16 + low); } @@ -84,7 +105,6 @@ namespace libtorrent return ret; } - std::string escape_string(const char* str, int len) { TORRENT_ASSERT(str != 0); @@ -148,4 +168,201 @@ namespace libtorrent } return ret.str(); } + + std::string base64encode(const std::string& s) + { + static const char base64_table[] = + { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' + }; + + unsigned char inbuf[3]; + unsigned char outbuf[4]; + + std::string ret; + for (std::string::const_iterator i = s.begin(); i != s.end();) + { + // available input is 1,2 or 3 bytes + // since we read 3 bytes at a time at most + int available_input = (std::min)(3, (int)std::distance(i, s.end())); + + // clear input buffer + std::fill(inbuf, inbuf+3, 0); + + // read a chunk of input into inbuf + std::copy(i, i + available_input, inbuf); + i += available_input; + + // encode inbuf to outbuf + outbuf[0] = (inbuf[0] & 0xfc) >> 2; + outbuf[1] = ((inbuf[0] & 0x03) << 4) | ((inbuf [1] & 0xf0) >> 4); + outbuf[2] = ((inbuf[1] & 0x0f) << 2) | ((inbuf [2] & 0xc0) >> 6); + outbuf[3] = inbuf[2] & 0x3f; + + // write output + for (int j = 0; j < available_input+1; ++j) + { + ret += base64_table[outbuf[j]]; + } + + // write pad + for (int j = 0; j < 3 - available_input; ++j) + { + ret += '='; + } + } + return ret; + } + + std::string base32encode(std::string const& s) + { + static const char base32_table[] = + { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', '2', '3', '4', '5', '6', '7' + }; + + int input_output_mapping[] = {0, 2, 4, 5, 7, 8}; + + unsigned char inbuf[5]; + unsigned char outbuf[8]; + + std::string ret; + for (std::string::const_iterator i = s.begin(); i != s.end();) + { + int available_input = (std::min)(5, (int)std::distance(i, s.end())); + + // clear input buffer + std::fill(inbuf, inbuf+5, 0); + + // read a chunk of input into inbuf + std::copy(i, i + available_input, inbuf); + i += available_input; + + // encode inbuf to outbuf + outbuf[0] = (inbuf[0] & 0xf8) >> 3; + outbuf[1] = ((inbuf[0] & 0x07) << 2) | ((inbuf[1] & 0xc0) >> 6); + outbuf[2] = ((inbuf[1] & 0x3e) >> 1); + outbuf[3] = ((inbuf[1] & 0x01) << 4) | ((inbuf[2] & 0xf0) >> 4); + outbuf[4] = ((inbuf[2] & 0x0f) << 1) | ((inbuf[3] & 0x80) >> 7); + outbuf[5] = ((inbuf[3] & 0x7c) >> 2); + outbuf[6] = ((inbuf[3] & 0x03) << 3) | ((inbuf[4] & 0xe0) >> 5); + outbuf[7] = inbuf[4] & 0x1f; + + // write output + int num_out = input_output_mapping[available_input]; + for (int j = 0; j < num_out; ++j) + { + ret += base32_table[outbuf[j]]; + } + + // write pad + for (int j = 0; j < 8 - num_out; ++j) + { + ret += '='; + } + } + return ret; + } + + std::string base32decode(std::string const& s) + { + unsigned char inbuf[8]; + unsigned char outbuf[5]; + + std::string ret; + for (std::string::const_iterator i = s.begin(); i != s.end();) + { + int available_input = (std::min)(8, (int)std::distance(i, s.end())); + + int pad_start = 0; + if (available_input < 8) pad_start = available_input; + + // clear input buffer + std::fill(inbuf, inbuf+8, 0); + for (int j = 0; j < available_input; ++j) + { + char in = std::toupper(*i++); + if (in >= 'A' && in <= 'Z') + inbuf[j] = in - 'A'; + else if (in >= '2' && in <= '7') + inbuf[j] = in - '2' + ('Z' - 'A') + 1; + else if (in == '=') + { + inbuf[j] = 0; + if (pad_start == 0) pad_start = j; + } + else if (in == '1') + inbuf[j] = 'I' - 'A'; + else + return std::string(); + TORRENT_ASSERT(inbuf[j] == (inbuf[j] & 0x1f)); + } + + // decode inbuf to outbuf + outbuf[0] = inbuf[0] << 3; + outbuf[0] |= inbuf[1] >> 2; + outbuf[1] = (inbuf[1] & 0x3) << 6; + outbuf[1] |= inbuf[2] << 1; + outbuf[1] |= (inbuf[3] & 0x10) >> 4; + outbuf[2] = (inbuf[3] & 0x0f) << 4; + outbuf[2] |= (inbuf[4] & 0x1e) >> 1; + outbuf[3] = (inbuf[4] & 0x01) << 7; + outbuf[3] |= (inbuf[5] & 0x1f) << 2; + outbuf[3] |= (inbuf[6] & 0x18) >> 3; + outbuf[4] = (inbuf[6] & 0x07) << 5; + outbuf[4] |= inbuf[7]; + + int input_output_mapping[] = {5, 1, 1, 2, 2, 3, 4, 4, 5}; + int num_out = input_output_mapping[pad_start]; + + // write output + std::copy(outbuf, outbuf + num_out, std::back_inserter(ret)); + } + return ret; + } + + boost::optional url_has_argument( + std::string const& url, std::string argument) + { + size_t i = url.find('?'); + if (i == std::string::npos) return boost::optional(); + ++i; + + argument += '='; + + if (url.compare(i, argument.size(), argument) == 0) + { + size_t pos = i + argument.size(); + return url.substr(pos, url.find('&', pos) - pos); + } + argument.insert(0, "&"); + i = url.find(argument, i); + if (i == std::string::npos) return boost::optional(); + size_t pos = i + argument.size(); + return url.substr(pos, url.find('&', pos) - pos); + } + + TORRENT_EXPORT std::string to_hex(std::string const& s) + { + std::string ret; + char* digits = "0123456789abcdef"; + for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) + { + ret += digits[((unsigned char)*i) >> 4]; + ret += digits[((unsigned char)*i) & 0xf]; + } + return ret; + } + } + diff --git a/libtorrent/src/file.cpp b/libtorrent/src/file.cpp index 5e01e1ae5..c6b79dce5 100755 --- a/libtorrent/src/file.cpp +++ b/libtorrent/src/file.cpp @@ -32,6 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/pch.hpp" +#include #ifdef _WIN32 // windows part #include "libtorrent/utf8.hpp" @@ -69,6 +70,7 @@ BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8); #include "libtorrent/file.hpp" #include #include +#include #ifndef O_BINARY #define O_BINARY 0 @@ -129,7 +131,6 @@ namespace namespace libtorrent { - namespace fs = boost::filesystem; const file::open_mode file::in(mode_in); @@ -157,9 +158,8 @@ namespace libtorrent close(); } - void open(fs::path const& path, int mode) + bool open(fs::path const& path, int mode) { - TORRENT_ASSERT(path.is_complete()); close(); #if defined(_WIN32) && defined(UNICODE) std::wstring wpath(safe_convert(path.native_file_string())); @@ -186,9 +186,12 @@ namespace libtorrent std::stringstream msg; msg << "open failed: '" << path.native_file_string() << "'. " << std::strerror(errno); - throw file_error(msg.str()); + if (!m_error) m_error.reset(new std::string); + *m_error = msg.str(); + return false; } m_open_mode = mode; + return true; } void close() @@ -218,7 +221,8 @@ namespace libtorrent { std::stringstream msg; msg << "read failed: " << std::strerror(errno); - throw file_error(msg.str()); + if (!m_error) m_error.reset(new std::string); + *m_error = msg.str(); } return ret; } @@ -242,12 +246,13 @@ namespace libtorrent { std::stringstream msg; msg << "write failed: " << std::strerror(errno); - throw file_error(msg.str()); + if (!m_error) m_error.reset(new std::string); + *m_error = msg.str(); } return ret; } - void set_size(size_type s) + bool set_size(size_type s) { #ifdef _WIN32 #error file.cpp is for posix systems only. use file_win.cpp on windows @@ -256,8 +261,11 @@ namespace libtorrent { std::stringstream msg; msg << "ftruncate failed: '" << std::strerror(errno); - throw file_error(msg.str()); + if (!m_error) m_error.reset(new std::string); + *m_error = msg.str(); + return false; } + return true; #endif } @@ -283,7 +291,9 @@ namespace libtorrent << "' fd: " << m_fd << " offset: " << offset << " seekdir: " << seekdir; - throw file_error(msg.str()); + if (!m_error) m_error.reset(new std::string); + *m_error = msg.str(); + return -1; } return ret; } @@ -300,8 +310,15 @@ namespace libtorrent #endif } + std::string const& error() const + { + if (!m_error) m_error.reset(new std::string); + return *m_error; + } + int m_fd; int m_open_mode; + mutable boost::scoped_ptr m_error; }; // pimpl forwardings @@ -314,9 +331,9 @@ namespace libtorrent file::~file() {} - void file::open(fs::path const& p, file::open_mode m) + bool file::open(fs::path const& p, file::open_mode m) { - m_impl->open(p, m.m_mask); + return m_impl->open(p, m.m_mask); } void file::close() @@ -334,9 +351,9 @@ namespace libtorrent return m_impl->read(buf, num_bytes); } - void file::set_size(size_type s) + bool file::set_size(size_type s) { - m_impl->set_size(s); + return m_impl->set_size(s); } size_type file::seek(size_type pos, file::seek_mode m) @@ -349,4 +366,9 @@ namespace libtorrent return m_impl->tell(); } + std::string const& file::error() const + { + return m_impl->error(); + } + } diff --git a/libtorrent/src/file_pool.cpp b/libtorrent/src/file_pool.cpp index 7bdf24085..19bdb4162 100644 --- a/libtorrent/src/file_pool.cpp +++ b/libtorrent/src/file_pool.cpp @@ -41,7 +41,8 @@ namespace libtorrent using boost::multi_index::nth_index; using boost::multi_index::get; - boost::shared_ptr file_pool::open_file(void* st, fs::path const& p, file::open_mode m) + boost::shared_ptr file_pool::open_file(void* st, fs::path const& p + , file::open_mode m, std::string& error) { TORRENT_ASSERT(st != 0); TORRENT_ASSERT(p.is_complete()); @@ -59,8 +60,9 @@ namespace libtorrent { // this means that another instance of the storage // is using the exact same file. - throw file_error("torrent uses the same file as another torrent " - "(" + p.string() + ")"); + error = "torrent uses the same file as another torrent " + "(" + p.string() + ")"; + return boost::shared_ptr(); } e.key = st; @@ -70,8 +72,13 @@ namespace libtorrent // the new read/write privilages i->file_ptr.reset(); TORRENT_ASSERT(e.file_ptr.unique()); - e.file_ptr.reset(); - e.file_ptr.reset(new file(p, m)); + e.file_ptr->close(); + if (!e.file_ptr->open(p, m)) + { + error = e.file_ptr->error(); + m_files.erase(i); + return boost::shared_ptr(); + } e.mode = m; } pt.replace(i, e); @@ -89,7 +96,18 @@ namespace libtorrent TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use)); lt.erase(i); } - lru_file_entry e(boost::shared_ptr(new file(p, m))); + lru_file_entry e; + e.file_ptr.reset(new file); + if (!e.file_ptr) + { + error = "no memory"; + return e.file_ptr; + } + if (!e.file_ptr->open(p, m)) + { + error = e.file_ptr->error(); + return boost::shared_ptr(); + } e.mode = m; e.key = st; e.file_path = p; @@ -97,6 +115,16 @@ namespace libtorrent return e.file_ptr; } + void file_pool::release(fs::path const& p) + { + boost::mutex::scoped_lock l(m_mutex); + + typedef nth_index::type path_view; + path_view& pt = get<0>(m_files); + path_view::iterator i = pt.find(p); + if (i != pt.end()) pt.erase(i); + } + void file_pool::release(void* st) { boost::mutex::scoped_lock l(m_mutex); diff --git a/libtorrent/src/file_storage.cpp b/libtorrent/src/file_storage.cpp new file mode 100644 index 000000000..a0c4145f3 --- /dev/null +++ b/libtorrent/src/file_storage.cpp @@ -0,0 +1,162 @@ +/* + +Copyright (c) 2003-2008, Arvid Norberg +All rights reserved. + +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. + +*/ + +#include "libtorrent/pch.hpp" + +#include "libtorrent/file_storage.hpp" + + +namespace libtorrent +{ + file_storage::file_storage() + : m_piece_length(0) + , m_total_size(0) + , m_num_pieces(0) + {} + + int file_storage::piece_size(int index) const + { + TORRENT_ASSERT(index >= 0 && index < num_pieces()); + if (index == num_pieces()-1) + { + int size = int(total_size() + - size_type(num_pieces() - 1) * piece_length()); + TORRENT_ASSERT(size > 0); + TORRENT_ASSERT(size <= piece_length()); + return int(size); + } + else + return piece_length(); + } + + void file_storage::rename_file(int index, std::string const& new_filename) + { + TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + m_files[index].path = new_filename; + } + + file_storage::iterator file_storage::file_at_offset(size_type offset) const + { + // TODO: do a binary search + std::vector::const_iterator i; + for (i = begin(); i != end(); ++i) + { + if (i->offset <= offset && i->offset + i->size > offset) + return i; + } + return i; + } + + std::vector file_storage::map_block(int piece, size_type offset + , int size_) const + { + TORRENT_ASSERT(num_files() > 0); + std::vector ret; + + size_type start = piece * (size_type)m_piece_length + offset; + size_type size = size_; + TORRENT_ASSERT(start + size <= m_total_size); + + // find the file iterator and file offset + // TODO: do a binary search on the file offsets + size_type file_offset = start; + std::vector::const_iterator file_iter; + + int counter = 0; + for (file_iter = begin();; ++counter, ++file_iter) + { + TORRENT_ASSERT(file_iter != end()); + if (file_offset < file_iter->size) + { + file_slice f; + f.file_index = counter; + f.offset = file_offset + file_iter->file_base; + f.size = (std::min)(file_iter->size - file_offset, (size_type)size); + size -= f.size; + file_offset += f.size; + ret.push_back(f); + } + + TORRENT_ASSERT(size >= 0); + if (size <= 0) break; + + file_offset -= file_iter->size; + } + return ret; + } + + peer_request file_storage::map_file(int file_index, size_type file_offset + , int size) const + { + TORRENT_ASSERT(file_index < num_files()); + TORRENT_ASSERT(file_index >= 0); + size_type offset = file_offset + at(file_index).offset; + + peer_request ret; + ret.piece = int(offset / piece_length()); + ret.start = int(offset - ret.piece * piece_length()); + ret.length = size; + return ret; + } + + void file_storage::add_file(fs::path const& file, size_type size) + { + TORRENT_ASSERT(size >= 0); + if (!file.has_branch_path()) + { + // you have already added at least one file with a + // path to the file (branch_path), which means that + // all the other files need to be in the same top + // directory as the first file. + TORRENT_ASSERT(m_files.empty()); + m_name = file.string(); + } + else + { + if (m_files.empty()) + m_name = *file.begin(); + } + TORRENT_ASSERT(m_name == *file.begin()); + file_entry e; + m_files.push_back(e); + m_files.back().size = size; + m_files.back().path = file; + m_files.back().offset = m_total_size; + m_total_size += size; + } + + void file_storage::add_file(file_entry const& e) + { + add_file(e.path, e.size); + } +} + diff --git a/libtorrent/src/file_win.cpp b/libtorrent/src/file_win.cpp index 7fde0028f..fb4f0ce9a 100644 --- a/libtorrent/src/file_win.cpp +++ b/libtorrent/src/file_win.cpp @@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include namespace { @@ -81,36 +82,7 @@ namespace return s; } } - - void throw_exception(const char* thrower) - { - DWORD err = GetLastError(); - -#ifdef UNICODE - wchar_t *wbuffer = 0; - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM - |FORMAT_MESSAGE_ALLOCATE_BUFFER - , 0, err, 0, (LPWSTR)&wbuffer, 0, 0); - auto_localfree auto_free(wbuffer); - std::string tmp_utf8; - libtorrent::wchar_utf8(wbuffer, tmp_utf8); - char const* buffer = tmp_utf8.c_str(); -#else - char* buffer = 0; - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM - |FORMAT_MESSAGE_ALLOCATE_BUFFER - , 0, err, 0, (LPSTR)&buffer, 0, 0); - auto_localfree auto_free(buffer); -#endif - - std::stringstream s; - s << (thrower ? thrower : "NULL") << ": " << (buffer ? buffer : "NULL"); - - throw libtorrent::file_error(s.str()); } -} namespace libtorrent { @@ -130,12 +102,42 @@ namespace libtorrent seek_end = FILE_END }; + void set_error(const char* thrower) + { + DWORD err = GetLastError(); + +#ifdef UNICODE + wchar_t *wbuffer = 0; + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM + |FORMAT_MESSAGE_ALLOCATE_BUFFER + , 0, err, 0, (LPWSTR)&wbuffer, 0, 0); + auto_localfree auto_free(wbuffer); + std::string tmp_utf8; + libtorrent::wchar_utf8(wbuffer, tmp_utf8); + char const* buffer = tmp_utf8.c_str(); +#else + char* buffer = 0; + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM + |FORMAT_MESSAGE_ALLOCATE_BUFFER + , 0, err, 0, (LPSTR)&buffer, 0, 0); + auto_localfree auto_free(buffer); +#endif + + std::stringstream s; + s << (thrower ? thrower : "NULL") << ": " << (buffer ? buffer : "NULL"); + + if (!m_error) m_error.reset(new std::string); + *m_error = s.str(); + } + impl() { m_file_handle = INVALID_HANDLE_VALUE; } - void open(const char *file_name, open_flags flags) + bool open(const char *file_name, open_flags flags) { TORRENT_ASSERT(file_name); TORRENT_ASSERT(flags & (read_flag | write_flag)); @@ -170,7 +172,10 @@ namespace libtorrent #endif if (new_handle == INVALID_HANDLE_VALUE) - throw_exception(file_name); + { + set_error(file_name); + return false; + } // try to make the file sparse if supported if (access_mask & GENERIC_WRITE) { @@ -181,6 +186,7 @@ namespace libtorrent // will only close old file if the open succeeded close(); m_file_handle = new_handle; + return true; } void close() @@ -211,7 +217,8 @@ namespace libtorrent , &bytes_written , 0)) { - throw_exception("file::write"); + set_error("file::write"); + return -1; } } return bytes_written; @@ -233,20 +240,23 @@ namespace libtorrent , &bytes_read , 0)) { - throw_exception("file::read"); + set_error("file::set_size"); + return -1; } } return bytes_read; } - void set_size(size_type s) + bool set_size(size_type s) { size_type pos = tell(); seek(s, seek_begin); if (FALSE == ::SetEndOfFile(m_file_handle)) - throw_exception("file::set_size"); - - seek(pos, seek_begin); + { + set_error("file::set_size"); + return false; + } + return true; } size_type seek(size_type pos, seek_mode from_where) @@ -261,7 +271,8 @@ namespace libtorrent , &offs , from_where)) { - throw_exception("file::seek"); + set_error("file::seek"); + return -1; } return offs.QuadPart; } @@ -278,7 +289,8 @@ namespace libtorrent , &offs , FILE_CURRENT)) { - throw_exception("file::tell"); + set_error("file::tell"); + return -1; } size_type pos = offs.QuadPart; @@ -299,9 +311,17 @@ namespace libtorrent return size; } */ + + std::string const& error() const + { + if (!m_error) m_error.reset(new std::string); + return *m_error; + } + private: HANDLE m_file_handle; + mutable boost::scoped_ptr m_error; }; } @@ -329,10 +349,10 @@ namespace libtorrent { } - void file::open(boost::filesystem::path const& p, open_mode m) + bool file::open(boost::filesystem::path const& p, open_mode m) { TORRENT_ASSERT(p.is_complete()); - m_impl->open(p.native_file_string().c_str(), impl::open_flags(m.m_mask)); + return m_impl->open(p.native_file_string().c_str(), impl::open_flags(m.m_mask)); } void file::close() @@ -350,9 +370,9 @@ namespace libtorrent return m_impl->read(buffer, num_bytes); } - void file::set_size(size_type s) + bool file::set_size(size_type s) { - m_impl->set_size(s); + return m_impl->set_size(s); } size_type file::seek(size_type pos, seek_mode m) @@ -364,4 +384,9 @@ namespace libtorrent { return m_impl->tell(); } + + std::string const& file::error() const + { + return m_impl->error(); + } } diff --git a/libtorrent/src/gzip.cpp b/libtorrent/src/gzip.cpp new file mode 100644 index 000000000..929816240 --- /dev/null +++ b/libtorrent/src/gzip.cpp @@ -0,0 +1,212 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +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. + +*/ + +#include "libtorrent/assert.hpp" + +#include "zlib.h" + +#include + +namespace +{ + enum + { + FTEXT = 0x01, + FHCRC = 0x02, + FEXTRA = 0x04, + FNAME = 0x08, + FCOMMENT = 0x10, + FRESERVED = 0xe0, + + GZIP_MAGIC0 = 0x1f, + GZIP_MAGIC1 = 0x8b + }; + +} + +namespace libtorrent +{ + // returns -1 if gzip header is invalid or the header size in bytes + int gzip_header(const char* buf, int size) + { + TORRENT_ASSERT(buf != 0); + TORRENT_ASSERT(size > 0); + + const unsigned char* buffer = reinterpret_cast(buf); + const int total_size = size; + + // The zip header cannot be shorter than 10 bytes + if (size < 10) return -1; + + // check the magic header of gzip + if ((buffer[0] != GZIP_MAGIC0) || (buffer[1] != GZIP_MAGIC1)) return -1; + + int method = buffer[2]; + int flags = buffer[3]; + + // check for reserved flag and make sure it's compressed with the correct metod + if (method != Z_DEFLATED || (flags & FRESERVED) != 0) return -1; + + // skip time, xflags, OS code + size -= 10; + buffer += 10; + + if (flags & FEXTRA) + { + int extra_len; + + if (size < 2) return -1; + + extra_len = (buffer[1] << 8) | buffer[0]; + + if (size < (extra_len+2)) return -1; + size -= (extra_len + 2); + buffer += (extra_len + 2); + } + + if (flags & FNAME) + { + while (size && *buffer) + { + --size; + ++buffer; + } + if (!size || *buffer) return -1; + + --size; + ++buffer; + } + + if (flags & FCOMMENT) + { + while (size && *buffer) + { + --size; + ++buffer; + } + if (!size || *buffer) return -1; + + --size; + ++buffer; + } + + if (flags & FHCRC) + { + if (size < 2) return -1; + + size -= 2; + buffer += 2; + } + + return total_size - size; + } + + bool inflate_gzip( + char const* in + , int size + , std::vector& buffer + , int maximum_size + , std::string& error) + { + TORRENT_ASSERT(maximum_size > 0); + + int header_len = gzip_header(in, size); + if (header_len < 0) + { + error = "invalid gzip header in tracker response"; + return true; + } + + // start off with one kilobyte and grow + // if needed + buffer.resize(1024); + + // initialize the zlib-stream + z_stream str; + + // subtract 8 from the end of the buffer since that's CRC32 and input size + // and those belong to the gzip file + str.avail_in = (int)size - header_len - 8; + str.next_in = reinterpret_cast(const_cast(in + header_len)); + str.next_out = reinterpret_cast(&buffer[0]); + str.avail_out = (int)buffer.size(); + str.zalloc = Z_NULL; + str.zfree = Z_NULL; + str.opaque = 0; + // -15 is really important. It will make inflate() not look for a zlib header + // and just deflate the buffer + if (inflateInit2(&str, -15) != Z_OK) + { + error = "gzip out of memory"; + return true; + } + + // inflate and grow inflate_buffer as needed + int ret = inflate(&str, Z_SYNC_FLUSH); + while (ret == Z_OK) + { + if (str.avail_out == 0) + { + if (buffer.size() >= (unsigned)maximum_size) + { + inflateEnd(&str); + error = "response too large"; + return true; + } + int new_size = (int)buffer.size() * 2; + if (new_size > maximum_size) + new_size = maximum_size; + int old_size = (int)buffer.size(); + + buffer.resize(new_size); + str.next_out = reinterpret_cast(&buffer[old_size]); + str.avail_out = new_size - old_size; + } + + ret = inflate(&str, Z_SYNC_FLUSH); + } + + buffer.resize(buffer.size() - str.avail_out); + inflateEnd(&str); + + if (ret != Z_STREAM_END) + { + error = "gzip error"; + return true; + } + + // commit the resulting buffer + return false; + } + +} + diff --git a/libtorrent/src/http_connection.cpp b/libtorrent/src/http_connection.cpp index 45ae7b7f3..5158796b6 100644 --- a/libtorrent/src/http_connection.cpp +++ b/libtorrent/src/http_connection.cpp @@ -31,60 +31,164 @@ POSSIBILITY OF SUCH DAMAGE. */ #include "libtorrent/http_connection.hpp" +#include "libtorrent/escape_string.hpp" +#include "libtorrent/instantiate_connection.hpp" +#include "libtorrent/gzip.hpp" +#include "libtorrent/parse_url.hpp" +#include "libtorrent/socket.hpp" +#include "libtorrent/connection_queue.hpp" #include #include -#include #include +#include using boost::bind; -namespace libtorrent -{ +namespace libtorrent { - enum { max_bottled_buffer = 1024 * 1024 }; +enum { max_bottled_buffer = 1024 * 1024 }; -void http_connection::get(std::string const& url, time_duration timeout - , int handle_redirects) + +void http_connection::get(std::string const& url, time_duration timeout, int prio + , proxy_settings const* ps, int handle_redirects, std::string const& user_agent + , address const& bind_addr) { std::string protocol; std::string auth; std::string hostname; std::string path; + char const* error; int port; - boost::tie(protocol, auth, hostname, port, path) = parse_url_components(url); + + boost::tie(protocol, auth, hostname, port, path, error) + = parse_url_components(url); + + if (error) + { + callback(asio::error::socket_type_not_supported); + return; + } + + TORRENT_ASSERT(prio >= 0 && prio < 2); + + bool ssl = false; + if (protocol == "https") ssl = true; +#ifndef TORRENT_USE_OPENSSL + if (ssl) + { + callback(asio::error::socket_type_not_supported); + return; + } +#endif + std::stringstream headers; - headers << "GET " << path << " HTTP/1.0\r\n" - "Host:" << hostname << - "\r\nConnection: close\r\n"; + if (ps && (ps->type == proxy_settings::http + || ps->type == proxy_settings::http_pw) + && !ssl) + { + // if we're using an http proxy and not an ssl + // connection, just do a regular http proxy request + headers << "GET " << url << " HTTP/1.0\r\n"; + if (ps->type == proxy_settings::http_pw) + headers << "Proxy-Authorization: Basic " << base64encode( + ps->username + ":" + ps->password) << "\r\n"; + hostname = ps->hostname; + port = ps->port; + ps = 0; + } + else + { + headers << "GET " << path << " HTTP/1.0\r\n" + "Host:" << hostname << "\r\n"; + } + if (!auth.empty()) headers << "Authorization: Basic " << base64encode(auth) << "\r\n"; - headers << "\r\n"; + + if (!user_agent.empty()) + headers << "User-Agent: " << user_agent << "\r\n"; + + headers << + "Connection: close\r\n" + "Accept-Encoding: gzip\r\n" + "\r\n"; + sendbuffer = headers.str(); m_url = url; - start(hostname, boost::lexical_cast(port), timeout, handle_redirects); + start(hostname, boost::lexical_cast(port), timeout, prio + , ps, ssl, handle_redirects, bind_addr); } void http_connection::start(std::string const& hostname, std::string const& port - , time_duration timeout, int handle_redirects) + , time_duration timeout, int prio, proxy_settings const* ps, bool ssl, int handle_redirects + , address const& bind_addr) { - m_redirects = handle_redirects; + TORRENT_ASSERT(prio >= 0 && prio < 2); + + m_redirects = handle_redirects; + if (ps) m_proxy = *ps; + m_timeout = timeout; - m_timer.expires_from_now(m_timeout); + error_code ec; + m_timer.expires_from_now(m_timeout, ec); m_timer.async_wait(bind(&http_connection::on_timeout , boost::weak_ptr(shared_from_this()), _1)); m_called = false; - m_parser.reset(); - m_recvbuffer.clear(); - m_read_pos = 0; - if (m_sock.is_open() && m_hostname == hostname && m_port == port) + m_parser.reset(); + m_recvbuffer.clear(); + m_read_pos = 0; + m_priority = prio; + + if (ec) { - asio::async_write(m_sock, asio::buffer(sendbuffer) + callback(ec); + return; + } + + if (m_sock.is_open() && m_hostname == hostname && m_port == port + && m_ssl == ssl && m_bind_addr == bind_addr) + { + async_write(m_sock, asio::buffer(sendbuffer) , bind(&http_connection::on_write, shared_from_this(), _1)); } else { - m_sock.close(); + m_ssl = ssl; + m_bind_addr = bind_addr; + error_code ec; + m_sock.close(ec); + +#ifdef TORRENT_USE_OPENSSL + if (m_ssl) + { + m_sock.instantiate >(m_resolver.get_io_service()); + ssl_stream& s = m_sock.get >(); + bool ret = instantiate_connection(m_resolver.get_io_service(), m_proxy, s.next_layer()); + TORRENT_ASSERT(ret); + } + else + { + m_sock.instantiate(m_resolver.get_io_service()); + bool ret = instantiate_connection(m_resolver.get_io_service() + , m_proxy, m_sock.get()); + TORRENT_ASSERT(ret); + } +#else + bool ret = instantiate_connection(m_resolver.get_io_service(), m_proxy, m_sock); + TORRENT_ASSERT(ret); +#endif + if (m_bind_addr != address_v4::any()) + { + error_code ec; + m_sock.bind(tcp::endpoint(m_bind_addr, 0), ec); + if (ec) + { + callback(ec); + return; + } + } + tcp::resolver::query query(hostname, port); m_resolver.async_resolve(query, bind(&http_connection::on_resolve , shared_from_this(), _1, _2)); @@ -95,52 +199,66 @@ void http_connection::start(std::string const& hostname, std::string const& port void http_connection::on_connect_timeout() { + TORRENT_ASSERT(m_connection_ticket >= 0); if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); m_connection_ticket = -1; - callback(asio::error::timed_out); - close(); + if (!m_endpoints.empty()) + { + m_sock.close(); + } + else + { + callback(asio::error::timed_out); + close(); + } } void http_connection::on_timeout(boost::weak_ptr p - , asio::error_code const& e) + , error_code const& e) { boost::shared_ptr c = p.lock(); if (!c) return; - if (c->m_connection_ticket > -1) c->m_cc.done(c->m_connection_ticket); - c->m_connection_ticket = -1; if (e == asio::error::operation_aborted) return; if (c->m_last_receive + c->m_timeout < time_now()) { - c->callback(asio::error::timed_out); - c->close(); + if (c->m_connection_ticket > -1 && !c->m_endpoints.empty()) + { + c->m_sock.close(); + error_code ec; + c->m_timer.expires_at(c->m_last_receive + c->m_timeout, ec); + c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1)); + } + else + { + c->callback(asio::error::timed_out); + c->close(); + } return; } if (!c->m_sock.is_open()) return; - - c->m_timer.expires_at(c->m_last_receive + c->m_timeout); + error_code ec; + c->m_timer.expires_at(c->m_last_receive + c->m_timeout, ec); c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1)); } void http_connection::close() { - m_timer.cancel(); - m_limiter_timer.cancel(); - m_sock.close(); + error_code ec; + m_timer.cancel(ec); + m_limiter_timer.cancel(ec); + m_sock.close(ec); m_hostname.clear(); m_port.clear(); - - if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); - m_connection_ticket = -1; - m_handler.clear(); + m_abort = true; } -void http_connection::on_resolve(asio::error_code const& e - , tcp::resolver::iterator i) +void http_connection::on_resolve(error_code const& e + , tcp::resolver::iterator i) { if (e) { @@ -149,53 +267,98 @@ void http_connection::on_resolve(asio::error_code const& e return; } TORRENT_ASSERT(i != tcp::resolver::iterator()); - m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, *i) + + std::transform(i, tcp::resolver::iterator(), std::back_inserter(m_endpoints) + , boost::bind(&tcp::resolver::iterator::value_type::endpoint, _1)); + + // The following statement causes msvc to crash (ICE). Since it's not + // necessary in the vast majority of cases, just ignore the endpoint + // order for windows +#if !defined _MSC_VER || _MSC_VER > 1310 + // sort the endpoints so that the ones with the same IP version as our + // bound listen socket are first. So that when contacting a tracker, + // we'll talk to it from the same IP that we're listening on + std::partition(m_endpoints.begin(), m_endpoints.end() + , boost::bind(&address::is_v4, boost::bind(&tcp::endpoint::address, _1)) == m_bind_addr.is_v4()); +#endif + + queue_connect(); +} + +void http_connection::queue_connect() +{ + TORRENT_ASSERT(!m_endpoints.empty()); + tcp::endpoint target = m_endpoints.front(); + m_endpoints.pop_front(); + + m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, target) , bind(&http_connection::on_connect_timeout, shared_from_this()) - , m_timeout); + , m_timeout, m_priority); } void http_connection::connect(int ticket, tcp::endpoint target_address) { m_connection_ticket = ticket; m_sock.async_connect(target_address, boost::bind(&http_connection::on_connect - , shared_from_this(), _1/*, ++i*/)); + , shared_from_this(), _1)); } -void http_connection::on_connect(asio::error_code const& e - /*, tcp::resolver::iterator i*/) +void http_connection::on_connect(error_code const& e) { + if (m_connection_ticket >= 0) + { + m_cc.done(m_connection_ticket); + m_connection_ticket = -1; + } + + m_last_receive = time_now(); if (!e) { - m_last_receive = time_now(); if (m_connect_handler) m_connect_handler(*this); - asio::async_write(m_sock, asio::buffer(sendbuffer) + async_write(m_sock, asio::buffer(sendbuffer) , bind(&http_connection::on_write, shared_from_this(), _1)); } -/* else if (i != tcp::resolver::iterator()) + else if (!m_endpoints.empty() && !m_abort) { // The connection failed. Try the next endpoint in the list. m_sock.close(); - m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, *i) - , bind(&http_connection::on_connect_timeout, shared_from_this()) - , m_timeout); + queue_connect(); } -*/ else + else { callback(e); close(); } } -void http_connection::callback(asio::error_code const& e, char const* data, int size) +void http_connection::callback(error_code const& e, char const* data, int size) { if (!m_bottled || !m_called) { + std::vector buf; + if (m_bottled && m_parser.finished()) + { + std::string const& encoding = m_parser.header("content-encoding"); + if (encoding == "gzip" || encoding == "x-gzip") + { + std::string error; + if (inflate_gzip(data, size, buf, max_bottled_buffer, error)) + { + if (m_handler) m_handler(asio::error::fault, m_parser, data, size, *this); + close(); + return; + } + data = &buf[0]; + size = int(buf.size()); + } + } m_called = true; + m_timer.cancel(); if (m_handler) m_handler(e, m_parser, data, size, *this); } } -void http_connection::on_write(asio::error_code const& e) +void http_connection::on_write(error_code const& e) { if (e) { @@ -214,7 +377,7 @@ void http_connection::on_write(asio::error_code const& e) if (m_download_quota == 0) { if (!m_limiter_timer_active) - on_assign_bandwidth(asio::error_code()); + on_assign_bandwidth(error_code()); return; } } @@ -224,7 +387,7 @@ void http_connection::on_write(asio::error_code const& e) , shared_from_this(), _1, _2)); } -void http_connection::on_read(asio::error_code const& e +void http_connection::on_read(error_code const& e , std::size_t bytes_transferred) { if (m_rate_limit) @@ -263,15 +426,13 @@ void http_connection::on_read(asio::error_code const& e { libtorrent::buffer::const_interval rcv_buf(&m_recvbuffer[0] , &m_recvbuffer[0] + m_read_pos); - try + bool error = false; + m_parser.incoming(rcv_buf, error); + if (error) { - m_parser.incoming(rcv_buf); - } - catch (std::exception&) - { - m_timer.cancel(); - callback(asio::error::fault, 0, 0); - close(); + // HTTP parse error + error_code ec = asio::error::fault; + callback(ec, 0, 0); return; } @@ -292,14 +453,17 @@ void http_connection::on_read(asio::error_code const& e return; } - try + error_code ec; + m_sock.close(ec); + using boost::tuples::ignore; + char const* error; + boost::tie(ignore, ignore, ignore, ignore, ignore, error) + = parse_url_components(location); + if (error == 0) { - asio::error_code ec; - m_sock.close(ec); - get(location, m_timeout, m_redirects - 1); - return; + get(location, m_timeout, m_priority, &m_proxy, m_redirects - 1); } - catch (std::exception& e) + else { // some broken web servers send out relative paths // in the location header. @@ -316,16 +480,7 @@ void http_connection::on_read(asio::error_code const& e } url += location; - try - { - get(url, m_timeout, m_redirects - 1); - } - catch (std::exception& e) - { - // location header is invalid - callback(asio::error::fault); - close(); - } + get(url, m_timeout, m_priority, &m_proxy, m_redirects - 1); } return; } @@ -343,7 +498,8 @@ void http_connection::on_read(asio::error_code const& e } else if (m_bottled && m_parser.finished()) { - m_timer.cancel(); + error_code ec; + m_timer.cancel(ec); callback(e, m_parser.get_body().begin, m_parser.get_body().left()); } } @@ -370,7 +526,7 @@ void http_connection::on_read(asio::error_code const& e if (m_download_quota == 0) { if (!m_limiter_timer_active) - on_assign_bandwidth(asio::error_code()); + on_assign_bandwidth(error_code()); return; } } @@ -380,7 +536,7 @@ void http_connection::on_read(asio::error_code const& e , shared_from_this(), _1, _2)); } -void http_connection::on_assign_bandwidth(asio::error_code const& e) +void http_connection::on_assign_bandwidth(error_code const& e) { if ((e == asio::error::operation_aborted && m_limiter_timer_active) @@ -407,8 +563,9 @@ void http_connection::on_assign_bandwidth(asio::error_code const& e) , bind(&http_connection::on_read , shared_from_this(), _1, _2)); + error_code ec; m_limiter_timer_active = true; - m_limiter_timer.expires_from_now(milliseconds(250)); + m_limiter_timer.expires_from_now(milliseconds(250), ec); m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth , shared_from_this(), _1)); } @@ -419,8 +576,9 @@ void http_connection::rate_limit(int limit) if (!m_limiter_timer_active) { + error_code ec; m_limiter_timer_active = true; - m_limiter_timer.expires_from_now(milliseconds(250)); + m_limiter_timer.expires_from_now(milliseconds(250), ec); m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth , shared_from_this(), _1)); } diff --git a/libtorrent/src/http_parser.cpp b/libtorrent/src/http_parser.cpp new file mode 100755 index 000000000..eb717420f --- /dev/null +++ b/libtorrent/src/http_parser.cpp @@ -0,0 +1,244 @@ +/* + +Copyright (c) 2008, Arvid Norberg +All rights reserved. + +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. + +*/ + +#include "libtorrent/pch.hpp" + +#include +#include + +#include "libtorrent/config.hpp" +#include "libtorrent/http_parser.hpp" +#include "libtorrent/assert.hpp" + +using namespace libtorrent; + +namespace +{ + char to_lower(char c) { return std::tolower(c); } +} + +namespace libtorrent +{ + http_parser::http_parser() + : m_recv_pos(0) + , m_status_code(-1) + , m_content_length(-1) + , m_state(read_status) + , m_recv_buffer(0, 0) + , m_body_start_pos(0) + , m_finished(false) + {} + + boost::tuple http_parser::incoming( + buffer::const_interval recv_buffer, bool& error) + { + TORRENT_ASSERT(recv_buffer.left() >= m_recv_buffer.left()); + boost::tuple ret(0, 0); + int start_pos = m_recv_buffer.left(); + + // early exit if there's nothing new in the receive buffer + if (start_pos == recv_buffer.left()) return ret; + m_recv_buffer = recv_buffer; + + if (m_state == error_state) + { + error = true; + return ret; + } + + char const* pos = recv_buffer.begin + m_recv_pos; + if (m_state == read_status) + { + TORRENT_ASSERT(!m_finished); + char const* newline = std::find(pos, recv_buffer.end, '\n'); + // if we don't have a full line yet, wait. + if (newline == recv_buffer.end) + { + boost::get<1>(ret) += m_recv_buffer.left() - start_pos; + return ret; + } + + if (newline == pos) + { + m_state = error_state; + error = true; + return ret; + } + + char const* line_end = newline; + if (pos != line_end && *(line_end - 1) == '\r') --line_end; + + std::istringstream line(std::string(pos, line_end)); + ++newline; + int incoming = (int)std::distance(pos, newline); + m_recv_pos += incoming; + boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos); + pos = newline; + + line >> m_protocol; + if (m_protocol.substr(0, 5) == "HTTP/") + { + line >> m_status_code; + std::getline(line, m_server_message); + } + else + { + m_method = m_protocol; + std::transform(m_method.begin(), m_method.end(), m_method.begin(), &to_lower); + m_protocol.clear(); + line >> m_path >> m_protocol; + m_status_code = 0; + } + m_state = read_header; + start_pos = pos - recv_buffer.begin; + } + + if (m_state == read_header) + { + TORRENT_ASSERT(!m_finished); + char const* newline = std::find(pos, recv_buffer.end, '\n'); + std::string line; + + while (newline != recv_buffer.end && m_state == read_header) + { + // if the LF character is preceeded by a CR + // charachter, don't copy it into the line string. + char const* line_end = newline; + if (pos != line_end && *(line_end - 1) == '\r') --line_end; + line.assign(pos, line_end); + ++newline; + m_recv_pos += newline - pos; + pos = newline; + + std::string::size_type separator = line.find(':'); + if (separator == std::string::npos) + { + // this means we got a blank line, + // the header is finished and the body + // starts. + m_state = read_body; + m_body_start_pos = m_recv_pos; + break; + } + + std::string name = line.substr(0, separator); + std::transform(name.begin(), name.end(), name.begin(), &to_lower); + ++separator; + // skip whitespace + while (separator < line.size() + && (line[separator] == ' ' || line[separator] == '\t')) + ++separator; + std::string value = line.substr(separator, std::string::npos); + m_header.insert(std::make_pair(name, value)); + + if (name == "content-length") + { +#ifdef WIN32 + m_content_length = _atoi64(value.c_str()); +#else + m_content_length = atoll(value.c_str()); +#endif + } + else if (name == "content-range") + { + std::stringstream range_str(value); + char dummy; + std::string bytes; + size_type range_start, range_end; + // apparently some web servers do not send the "bytes" + // in their content-range + if (value.find(' ') != std::string::npos) + range_str >> bytes; + range_str >> range_start >> dummy >> range_end; + if (!range_str || range_end < range_start) + { + m_state = error_state; + error = true; + return ret; + } + // the http range is inclusive + m_content_length = range_end - range_start + 1; + } + + TORRENT_ASSERT(m_recv_pos <= (int)recv_buffer.left()); + newline = std::find(pos, recv_buffer.end, '\n'); + } + boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos); + } + + if (m_state == read_body) + { + int incoming = recv_buffer.end - pos; + if (m_recv_pos - m_body_start_pos + incoming > m_content_length + && m_content_length >= 0) + incoming = m_content_length - m_recv_pos + m_body_start_pos; + + TORRENT_ASSERT(incoming >= 0); + m_recv_pos += incoming; + boost::get<0>(ret) += incoming; + + if (m_content_length >= 0 + && m_recv_pos - m_body_start_pos >= m_content_length) + { + m_finished = true; + } + } + return ret; + } + + buffer::const_interval http_parser::get_body() const + { + TORRENT_ASSERT(m_state == read_body); + if (m_content_length >= 0) + return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos + , m_recv_buffer.begin + (std::min)(size_type(m_recv_pos) + , m_body_start_pos + m_content_length)); + else + return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos + , m_recv_buffer.begin + m_recv_pos); + } + + void http_parser::reset() + { + m_recv_pos = 0; + m_body_start_pos = 0; + m_status_code = -1; + m_content_length = -1; + m_finished = false; + m_state = read_status; + m_recv_buffer.begin = 0; + m_recv_buffer.end = 0; + m_header.clear(); + } + +} + diff --git a/libtorrent/src/http_stream.cpp b/libtorrent/src/http_stream.cpp index 0973af798..eaa636bf1 100644 --- a/libtorrent/src/http_stream.cpp +++ b/libtorrent/src/http_stream.cpp @@ -33,18 +33,19 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/pch.hpp" #include "libtorrent/http_stream.hpp" -#include "libtorrent/tracker_manager.hpp" // for base64encode +#include "libtorrent/escape_string.hpp" // for base64encode namespace libtorrent { - void http_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i + void http_stream::name_lookup(error_code const& e, tcp::resolver::iterator i , boost::shared_ptr h) { if (e || i == tcp::resolver::iterator()) { (*h)(e); - close(); + error_code ec; + close(ec); return; } @@ -52,12 +53,13 @@ namespace libtorrent &http_stream::connected, this, _1, h)); } - void http_stream::connected(asio::error_code const& e, boost::shared_ptr h) + void http_stream::connected(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - close(); + error_code ec; + close(ec); return; } @@ -80,31 +82,33 @@ namespace libtorrent m_user + ":" + m_password) + "\r\n", p); } write_string("\r\n", p); - asio::async_write(m_sock, asio::buffer(m_buffer) + async_write(m_sock, asio::buffer(m_buffer) , boost::bind(&http_stream::handshake1, this, _1, h)); } - void http_stream::handshake1(asio::error_code const& e, boost::shared_ptr h) + void http_stream::handshake1(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - close(); + error_code ec; + close(ec); return; } // read one byte from the socket m_buffer.resize(1); - asio::async_read(m_sock, asio::buffer(m_buffer) + async_read(m_sock, asio::buffer(m_buffer) , boost::bind(&http_stream::handshake2, this, _1, h)); } - void http_stream::handshake2(asio::error_code const& e, boost::shared_ptr h) + void http_stream::handshake2(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - close(); + error_code ec; + close(ec); return; } @@ -134,7 +138,8 @@ namespace libtorrent if (status == 0) { (*h)(asio::error::operation_not_supported); - close(); + error_code ec; + close(ec); return; } @@ -143,7 +148,8 @@ namespace libtorrent if (code != 200) { (*h)(asio::error::operation_not_supported); - close(); + error_code ec; + close(ec); return; } @@ -154,7 +160,7 @@ namespace libtorrent // read another byte from the socket m_buffer.resize(read_pos + 1); - asio::async_read(m_sock, asio::buffer(&m_buffer[0] + read_pos, 1) + async_read(m_sock, asio::buffer(&m_buffer[0] + read_pos, 1) , boost::bind(&http_stream::handshake2, this, _1, h)); } diff --git a/libtorrent/src/http_tracker_connection.cpp b/libtorrent/src/http_tracker_connection.cpp index 5c14d818a..b87ee0a28 100755 --- a/libtorrent/src/http_tracker_connection.cpp +++ b/libtorrent/src/http_tracker_connection.cpp @@ -40,7 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include "libtorrent/config.hpp" -#include "zlib.h" +#include "libtorrent/gzip.hpp" #ifdef _MSC_VER #pragma warning(push, 1) @@ -54,815 +54,214 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/tracker_manager.hpp" #include "libtorrent/http_tracker_connection.hpp" +#include "libtorrent/http_connection.hpp" #include "libtorrent/entry.hpp" #include "libtorrent/bencode.hpp" #include "libtorrent/torrent.hpp" #include "libtorrent/io.hpp" -#include "libtorrent/instantiate_connection.hpp" +#include "libtorrent/socket.hpp" using namespace libtorrent; using boost::bind; -namespace -{ - enum - { - minimum_tracker_response_length = 3, - http_buffer_size = 2048 - }; - - - enum - { - FTEXT = 0x01, - FHCRC = 0x02, - FEXTRA = 0x04, - FNAME = 0x08, - FCOMMENT = 0x10, - FRESERVED = 0xe0, - - GZIP_MAGIC0 = 0x1f, - GZIP_MAGIC1 = 0x8b - }; - -} - -namespace -{ - bool url_has_argument(std::string const& url, std::string argument) - { - size_t i = url.find('?'); - if (i == std::string::npos) return false; - - argument += '='; - - if (url.compare(i + 1, argument.size(), argument) == 0) return true; - argument.insert(0, "&"); - return url.find(argument, i) - != std::string::npos; - } - - char to_lower(char c) { return std::tolower(c); } -} - namespace libtorrent { - http_parser::http_parser() - : m_recv_pos(0) - , m_status_code(-1) - , m_content_length(-1) - , m_state(read_status) - , m_recv_buffer(0, 0) - , m_body_start_pos(0) - , m_finished(false) - {} - - boost::tuple http_parser::incoming(buffer::const_interval recv_buffer) - { - TORRENT_ASSERT(recv_buffer.left() >= m_recv_buffer.left()); - boost::tuple ret(0, 0); - int start_pos = m_recv_buffer.left(); - - // early exit if there's nothing new in the receive buffer - if (start_pos == recv_buffer.left()) return ret; - m_recv_buffer = recv_buffer; - - char const* pos = recv_buffer.begin + m_recv_pos; - if (m_state == read_status) - { - TORRENT_ASSERT(!m_finished); - char const* newline = std::find(pos, recv_buffer.end, '\n'); - // if we don't have a full line yet, wait. - if (newline == recv_buffer.end) - { - boost::get<1>(ret) += m_recv_buffer.left() - start_pos; - return ret; - } - - if (newline == pos) - throw std::runtime_error("unexpected newline in HTTP response"); - - char const* line_end = newline; - if (pos != line_end && *(line_end - 1) == '\r') --line_end; - - std::istringstream line(std::string(pos, line_end)); - ++newline; - int incoming = (int)std::distance(pos, newline); - m_recv_pos += incoming; - boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos); - pos = newline; - - line >> m_protocol; - if (m_protocol.substr(0, 5) == "HTTP/") - { - line >> m_status_code; - std::getline(line, m_server_message); - } - else - { - m_method = m_protocol; - std::transform(m_method.begin(), m_method.end(), m_method.begin(), &to_lower); - m_protocol.clear(); - line >> m_path >> m_protocol; - m_status_code = 0; - } - m_state = read_header; - start_pos = pos - recv_buffer.begin; - } - - if (m_state == read_header) - { - TORRENT_ASSERT(!m_finished); - char const* newline = std::find(pos, recv_buffer.end, '\n'); - std::string line; - - while (newline != recv_buffer.end && m_state == read_header) - { - // if the LF character is preceeded by a CR - // charachter, don't copy it into the line string. - char const* line_end = newline; - if (pos != line_end && *(line_end - 1) == '\r') --line_end; - line.assign(pos, line_end); - ++newline; - m_recv_pos += newline - pos; - pos = newline; - - std::string::size_type separator = line.find(':'); - if (separator == std::string::npos) - { - // this means we got a blank line, - // the header is finished and the body - // starts. - m_state = read_body; - m_body_start_pos = m_recv_pos; - break; - } - - std::string name = line.substr(0, separator); - std::transform(name.begin(), name.end(), name.begin(), &to_lower); - ++separator; - // skip whitespace - while (separator < line.size() - && (line[separator] == ' ' || line[separator] == '\t')) - ++separator; - std::string value = line.substr(separator, std::string::npos); - m_header.insert(std::make_pair(name, value)); - - if (name == "content-length") - { - try - { - m_content_length = boost::lexical_cast(value); - } - catch(boost::bad_lexical_cast&) {} - } - else if (name == "content-range") - { - std::stringstream range_str(value); - char dummy; - std::string bytes; - size_type range_start, range_end; - // apparently some web servers do not send the "bytes" - // in their content-range - if (value.find(' ') != std::string::npos) - range_str >> bytes; - range_str >> range_start >> dummy >> range_end; - if (!range_str || range_end < range_start - || range_end - range_start + 1 >= (std::numeric_limits::max)()) - { - throw std::runtime_error("invalid content-range in HTTP response: " + range_str.str()); - } - // the http range is inclusive - m_content_length = int(range_end - range_start + 1); - } - - TORRENT_ASSERT(m_recv_pos <= (int)recv_buffer.left()); - newline = std::find(pos, recv_buffer.end, '\n'); - } - boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos); - } - - if (m_state == read_body) - { - int incoming = recv_buffer.end - pos; - if (m_recv_pos - m_body_start_pos + incoming > m_content_length - && m_content_length >= 0) - incoming = m_content_length - m_recv_pos + m_body_start_pos; - - TORRENT_ASSERT(incoming >= 0); - m_recv_pos += incoming; - boost::get<0>(ret) += incoming; - - if (m_content_length >= 0 - && m_recv_pos - m_body_start_pos >= m_content_length) - { - m_finished = true; - } - } - return ret; - } - - buffer::const_interval http_parser::get_body() const - { - TORRENT_ASSERT(m_state == read_body); - if (m_content_length >= 0) - return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos - , m_recv_buffer.begin + (std::min)(m_recv_pos - , m_body_start_pos + m_content_length)); - else - return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos - , m_recv_buffer.begin + m_recv_pos); - } - - void http_parser::reset() - { - m_recv_pos = 0; - m_body_start_pos = 0; - m_status_code = -1; - m_content_length = -1; - m_finished = false; - m_state = read_status; - m_recv_buffer.begin = 0; - m_recv_buffer.end = 0; - m_header.clear(); - } http_tracker_connection::http_tracker_connection( - asio::strand& str + io_service& ios , connection_queue& cc , tracker_manager& man , tracker_request const& req - , std::string const& hostname - , unsigned short port - , std::string request , address bind_infc , boost::weak_ptr c , session_settings const& stn , proxy_settings const& ps , std::string const& auth) - : tracker_connection(man, req, str, bind_infc, c) + : tracker_connection(man, req, ios, bind_infc, c) , m_man(man) - , m_strand(str) - , m_name_lookup(m_strand.io_service()) - , m_port(port) - , m_recv_pos(0) - , m_buffer(http_buffer_size) - , m_settings(stn) - , m_proxy(ps) - , m_password(auth) - , m_timed_out(false) - , m_connection_ticket(-1) - , m_cc(cc) { - m_send_buffer.assign("GET "); + // TODO: authentication + std::string url = req.url; - // should we use the proxy? - if (m_proxy.type == proxy_settings::http - || m_proxy.type == proxy_settings::http_pw) - { - m_send_buffer += "http://"; - m_send_buffer += hostname; - if (port != 80) - { - m_send_buffer += ":"; - m_send_buffer += boost::lexical_cast(port); - } - } - - if (tracker_req().kind == tracker_request::scrape_request) + if (req.kind == tracker_request::scrape_request) { // find and replace "announce" with "scrape" // in request - std::size_t pos = request.find("announce"); + std::size_t pos = url.find("announce"); if (pos == std::string::npos) - throw std::runtime_error("scrape is not available on url: '" - + tracker_req().url +"'"); - request.replace(pos, 8, "scrape"); + { + fail(-1, ("scrape is not available on url: '" + + req.url +"'").c_str()); + return; + } + url.replace(pos, 8, "scrape"); } - - m_send_buffer += request; - + // if request-string already contains // some parameters, append an ampersand instead // of a question mark - size_t arguments_start = request.find('?'); + size_t arguments_start = url.find('?'); if (arguments_start != std::string::npos) - m_send_buffer += "&"; + url += "&"; else - m_send_buffer += "?"; + url += "?"; - if (!url_has_argument(request, "info_hash")) + url += "info_hash="; + url += escape_string( + reinterpret_cast(req.info_hash.begin()), 20); + + if (req.kind == tracker_request::announce_request) { - m_send_buffer += "info_hash="; - m_send_buffer += escape_string( - reinterpret_cast(req.info_hash.begin()), 20); - m_send_buffer += '&'; - } + url += "&peer_id="; + url += escape_string( + reinterpret_cast(req.pid.begin()), 20); - if (tracker_req().kind == tracker_request::announce_request) - { - if (!url_has_argument(request, "peer_id")) - { - m_send_buffer += "peer_id="; - m_send_buffer += escape_string( - reinterpret_cast(req.pid.begin()), 20); - m_send_buffer += '&'; - } + url += "&port="; + url += boost::lexical_cast(req.listen_port); - if (!url_has_argument(request, "port")) - { - m_send_buffer += "port="; - m_send_buffer += boost::lexical_cast(req.listen_port); - m_send_buffer += '&'; - } + url += "&uploaded="; + url += boost::lexical_cast(req.uploaded); - if (!url_has_argument(request, "uploaded")) - { - m_send_buffer += "uploaded="; - m_send_buffer += boost::lexical_cast(req.uploaded); - m_send_buffer += '&'; - } + url += "&downloaded="; + url += boost::lexical_cast(req.downloaded); - if (!url_has_argument(request, "downloaded")) - { - m_send_buffer += "downloaded="; - m_send_buffer += boost::lexical_cast(req.downloaded); - m_send_buffer += '&'; - } - - if (!url_has_argument(request, "left")) - { - m_send_buffer += "left="; - m_send_buffer += boost::lexical_cast(req.left); - m_send_buffer += '&'; - } + url += "&left="; + url += boost::lexical_cast(req.left); if (req.event != tracker_request::none) { - if (!url_has_argument(request, "event")) - { - const char* event_string[] = {"completed", "started", "stopped"}; - m_send_buffer += "event="; - m_send_buffer += event_string[req.event - 1]; - m_send_buffer += '&'; - } - } - if (!url_has_argument(request, "key")) - { - m_send_buffer += "key="; - std::stringstream key_string; - key_string << std::hex << req.key; - m_send_buffer += key_string.str(); - m_send_buffer += '&'; + const char* event_string[] = {"completed", "started", "stopped"}; + url += "&event="; + url += event_string[req.event - 1]; } - if (!url_has_argument(request, "compact")) + url += "&key="; + std::stringstream key_string; + key_string << std::hex << req.key; + url += key_string.str(); + + url += "&compact=1"; + + url += "&numwant="; + url += boost::lexical_cast( + (std::min)(req.num_want, 999)); + + if (stn.announce_ip != address()) { - m_send_buffer += "compact=1&"; - } - if (!url_has_argument(request, "numwant")) - { - m_send_buffer += "numwant="; - m_send_buffer += boost::lexical_cast( - (std::min)(req.num_want, 999)); - m_send_buffer += '&'; - } - if (m_settings.announce_ip != address() && !url_has_argument(request, "ip")) - { - m_send_buffer += "ip="; - m_send_buffer += m_settings.announce_ip.to_string(); - m_send_buffer += '&'; + url += "&ip="; + url += stn.announce_ip.to_string(); } #ifndef TORRENT_DISABLE_ENCRYPTION - m_send_buffer += "supportcrypto=1&"; + url += "&supportcrypto=1"; #endif - - if (!url_has_argument(request, "ipv6") && !req.ipv6.empty()) - { - m_send_buffer += "ipv6="; - m_send_buffer += req.ipv6; - m_send_buffer += '&'; - } + url += "&ipv6="; + url += req.ipv6; // extension that tells the tracker that // we don't need any peer_id's in the response - if (!url_has_argument(request, "no_peer_id")) - { - m_send_buffer += "no_peer_id=1"; - } - else - { - // remove the trailing '&' - m_send_buffer.resize(m_send_buffer.size() - 1); - } + url += "&no_peer_id=1"; } - m_send_buffer += " HTTP/1.0\r\nAccept-Encoding: gzip\r\n" - "User-Agent: "; - m_send_buffer += m_settings.user_agent; - m_send_buffer += "\r\n" - "Host: "; - m_send_buffer += hostname; - if (port != 80) - { - m_send_buffer += ':'; - m_send_buffer += boost::lexical_cast(port); - } - if (m_proxy.type == proxy_settings::http_pw) - { - m_send_buffer += "\r\nProxy-Authorization: Basic "; - m_send_buffer += base64encode(m_proxy.username + ":" + m_proxy.password); - } - if (!auth.empty()) - { - m_send_buffer += "\r\nAuthorization: Basic "; - m_send_buffer += base64encode(auth); - } - m_send_buffer += "\r\n\r\n"; + m_tracker_connection.reset(new http_connection(ios, cc + , boost::bind(&http_tracker_connection::on_response, self(), _1, _2, _3, _4))); + + int timeout = req.event==tracker_request::stopped + ?stn.stop_tracker_timeout + :stn.tracker_completion_timeout; + + m_tracker_connection->get(url, seconds(timeout) + , 1, &ps, 5, stn.user_agent, bind_infc); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) boost::shared_ptr cb = requester(); if (cb) { - cb->debug_log("==> TRACKER_REQUEST [ str: " + m_send_buffer + " ]"); - std::stringstream info_hash_str; - info_hash_str << req.info_hash; - cb->debug_log("info_hash: " - + boost::lexical_cast(req.info_hash)); - cb->debug_log("name lookup: " + hostname); + cb->debug_log("==> TRACKER_REQUEST [ url: " + url + " ]"); } #endif - - tcp::resolver::query q(hostname - , boost::lexical_cast(m_port)); - m_name_lookup.async_resolve(q, m_strand.wrap( - boost::bind(&http_tracker_connection::name_lookup, self(), _1, _2))); - set_timeout(req.event == tracker_request::stopped - ? m_settings.stop_tracker_timeout - : m_settings.tracker_completion_timeout - , m_settings.tracker_receive_timeout); - } - - void http_tracker_connection::on_timeout() - { - m_timed_out = true; - m_socket.close(); - m_name_lookup.cancel(); - if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); - m_connection_ticket = -1; - fail_timeout(); } void http_tracker_connection::close() { - asio::error_code ec; - m_socket.close(ec); - m_name_lookup.cancel(); - if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); - m_connection_ticket = -1; - m_timed_out = true; + if (m_tracker_connection) + { + m_tracker_connection->close(); + m_tracker_connection.reset(); + } tracker_connection::close(); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - boost::shared_ptr cb = requester(); - std::stringstream msg; - msg << "http_tracker_connection::close() " << m_man.num_requests(); - if (cb) cb->debug_log(msg.str()); -#endif } - void http_tracker_connection::name_lookup(asio::error_code const& error - , tcp::resolver::iterator i) try + void http_tracker_connection::on_response(error_code const& ec + , http_parser const& parser, char const* data, int size) { - boost::shared_ptr cb = requester(); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (cb) cb->debug_log("tracker name lookup handler called"); -#endif - if (error == asio::error::operation_aborted) return; - if (m_timed_out) return; + // keep this alive + boost::intrusive_ptr me(this); - if (error || i == tcp::resolver::iterator()) + if (ec && ec != asio::error::eof) { - fail(-1, error.message().c_str()); + fail(-1, ec.message().c_str()); return; } -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (cb) cb->debug_log("tracker name lookup successful"); -#endif - restart_read_timeout(); - - // look for an address that has the same kind as the one - // we're listening on. To make sure the tracker get our - // correct listening address. - tcp::resolver::iterator target = i; - tcp::resolver::iterator end; - tcp::endpoint target_address = *i; - for (; target != end && target->endpoint().address().is_v4() - != bind_interface().is_v4(); ++target); - if (target == end) - { - TORRENT_ASSERT(target_address.address().is_v4() != bind_interface().is_v4()); - if (cb) - { - std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6"; - std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6"; - cb->tracker_warning("the tracker only resolves to an " - + tracker_address_type + " address, and you're listening on an " - + bind_address_type + " socket. This may prevent you from receiving incoming connections."); - } - } - else - { - target_address = *target; - } - - if (cb) cb->m_tracker_address = target_address; - bool ret = instantiate_connection(m_strand.io_service(), m_proxy, m_socket); - - TORRENT_ASSERT(ret); - - if (m_proxy.type == proxy_settings::http - || m_proxy.type == proxy_settings::http_pw) - { - // the tracker connection will talk immediately to - // the proxy, without requiring CONNECT support - m_socket.get().set_no_connect(true); - } - - m_socket.open(target_address.protocol()); - m_socket.bind(tcp::endpoint(bind_interface(), 0)); - m_cc.enqueue(bind(&http_tracker_connection::connect, self(), _1, target_address) - , bind(&http_tracker_connection::on_timeout, self()) - , seconds(m_settings.tracker_receive_timeout)); - } - catch (std::exception& e) - { - fail(-1, e.what()); - }; - - void http_tracker_connection::connect(int ticket, tcp::endpoint target_address) - { - m_connection_ticket = ticket; - m_socket.async_connect(target_address, bind(&http_tracker_connection::connected, self(), _1)); - } - - void http_tracker_connection::connected(asio::error_code const& error) try - { - if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); - m_connection_ticket = -1; - if (error == asio::error::operation_aborted) return; - if (m_timed_out) return; - if (error) - { - fail(-1, error.message().c_str()); - return; - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - boost::shared_ptr cb = requester(); - if (cb) cb->debug_log("tracker connection successful"); -#endif - - restart_read_timeout(); - async_write(m_socket, asio::buffer(m_send_buffer.c_str() - , m_send_buffer.size()), bind(&http_tracker_connection::sent - , self(), _1)); - } - catch (std::exception& e) - { - fail(-1, e.what()); - } - - void http_tracker_connection::sent(asio::error_code const& error) try - { - if (error == asio::error::operation_aborted) return; - if (m_timed_out) return; - if (error) - { - fail(-1, error.message().c_str()); - return; - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - boost::shared_ptr cb = requester(); - if (cb) cb->debug_log("tracker send data completed"); -#endif - restart_read_timeout(); - TORRENT_ASSERT(m_buffer.size() - m_recv_pos > 0); - m_socket.async_read_some(asio::buffer(&m_buffer[m_recv_pos] - , m_buffer.size() - m_recv_pos), bind(&http_tracker_connection::receive - , self(), _1, _2)); - } - catch (std::exception& e) - { - fail(-1, e.what()); - }; // msvc 7.1 seems to require this semi-colon - - - void http_tracker_connection::receive(asio::error_code const& error - , std::size_t bytes_transferred) try - { - if (error == asio::error::operation_aborted) return; - if (m_timed_out) return; - - if (error) - { - if (error == asio::error::eof) - { - on_response(); - close(); - return; - } - - fail(-1, error.message().c_str()); - return; - } - - restart_read_timeout(); - TORRENT_ASSERT(bytes_transferred > 0); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - boost::shared_ptr cb = requester(); - if (cb) cb->debug_log("tracker connection reading " - + boost::lexical_cast(bytes_transferred)); -#endif - - m_recv_pos += bytes_transferred; - m_parser.incoming(buffer::const_interval(&m_buffer[0] - , &m_buffer[0] + m_recv_pos)); - - // if the receive buffer is full, expand it with http_buffer_size - if ((int)m_buffer.size() == m_recv_pos) - { - if ((int)m_buffer.size() >= m_settings.tracker_maximum_response_length) - { - fail(200, "too large tracker response"); - return; - } - TORRENT_ASSERT(http_buffer_size > 0); - if ((int)m_buffer.size() + http_buffer_size - > m_settings.tracker_maximum_response_length) - m_buffer.resize(m_settings.tracker_maximum_response_length); - else - m_buffer.resize(m_buffer.size() + http_buffer_size); - } - - if (m_parser.header_finished()) - { - int cl = atoi(m_parser.header("content-length").c_str()); - if (cl > m_settings.tracker_maximum_response_length) - { - fail(-1, "content-length is greater than maximum response length"); - return; - } - - if (cl > 0 && cl < minimum_tracker_response_length && m_parser.status_code() == 200) - { - fail(-1, "content-length is smaller than minimum response length"); - return; - } - } - - if (m_parser.finished()) - { - on_response(); - close(); - return; - } - - TORRENT_ASSERT(m_buffer.size() - m_recv_pos > 0); - m_socket.async_read_some(asio::buffer(&m_buffer[m_recv_pos] - , m_buffer.size() - m_recv_pos), bind(&http_tracker_connection::receive - , self(), _1, _2)); - } - catch (std::exception& e) - { - fail(-1, e.what()); - }; - - void http_tracker_connection::on_response() - { - if (!m_parser.header_finished()) + if (!parser.header_finished()) { fail(-1, "premature end of file"); return; } - - std::string location = m_parser.header("location"); - boost::shared_ptr cb = requester(); + if (parser.status_code() != 200) + { + fail(parser.status_code(), parser.message().c_str()); + return; + } + + if (ec && ec != asio::error::eof) + { + fail(parser.status_code(), ec.message().c_str()); + return; + } - if (m_parser.status_code() >= 300 && m_parser.status_code() < 400) - { - if (location.empty()) - { - std::string error_str = "got redirection response ("; - error_str += boost::lexical_cast(m_parser.status_code()); - error_str += ") without 'Location' header"; - fail(-1, error_str.c_str()); - return; - } - - // if the protocol isn't specified, assume http - if (location.compare(0, 7, "http://") != 0 - && location.compare(0, 6, "udp://") != 0) - { - location.insert(0, "http://"); - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (cb) cb->debug_log("Redirecting to \"" + location + "\""); -#endif - if (cb) cb->tracker_warning("Redirecting to \"" + location + "\""); - tracker_request req = tracker_req(); - - req.url = location; - - m_man.queue_request(m_strand, m_cc, req - , m_password, bind_interface(), m_requester); - close(); - return; - } - - if (m_parser.status_code() != 200) - { - fail(m_parser.status_code(), m_parser.message().c_str()); - return; - } - - buffer::const_interval buf(&m_buffer[0] + m_parser.body_start(), &m_buffer[0] + m_recv_pos); - - std::string content_encoding = m_parser.header("content-encoding"); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (cb) cb->debug_log("content-encoding: \"" + content_encoding + "\""); -#endif - - if (content_encoding == "gzip" || content_encoding == "x-gzip") - { - if (!cb) - { - close(); - return; - } - m_buffer.erase(m_buffer.begin(), m_buffer.begin() + m_parser.body_start()); - if (inflate_gzip(m_buffer, tracker_req(), cb.get(), - m_settings.tracker_maximum_response_length)) - { - close(); - return; - } - buf.begin = &m_buffer[0]; - buf.end = &m_buffer[0] + m_buffer.size(); - } - else if (!content_encoding.empty()) - { - std::string error_str = "unknown content encoding in response: \""; - error_str += content_encoding; - error_str += "\""; - fail(-1, error_str.c_str()); - return; - } - // handle tracker response - try + entry e; + e = bdecode(data, data + size); + + if (e.type() != entry::undefined_t) { - entry e = bdecode(buf.begin, buf.end); - parse(e); + parse(parser.status_code(), e); } - catch (std::exception& e) + else { - std::string error_str(e.what()); - error_str += ": \""; - for (char const* i = buf.begin, *end(buf.end); i != end; ++i) + std::string error_str("invalid bencoding of tracker response: \""); + for (char const* i = data, *end(data + size); i != end; ++i) { if (std::isprint(*i)) error_str += *i; else error_str += "0x" + boost::lexical_cast((unsigned int)*i) + " "; } error_str += "\""; - fail(m_parser.status_code(), error_str.c_str()); + fail(parser.status_code(), error_str.c_str()); } - #ifndef NDEBUG - catch (...) - { - TORRENT_ASSERT(false); - } - #endif close(); } - peer_entry http_tracker_connection::extract_peer_info(const entry& info) + bool http_tracker_connection::extract_peer_info(const entry& info, peer_entry& ret) { - peer_entry ret; - // extract peer id (if any) + if (info.type() != entry::dictionary_t) + { + fail(-1, "invalid response from tracker (invalid peer entry)"); + return false; + } entry const* i = info.find_key("peer id"); if (i != 0) { - if (i->string().length() != 20) - throw std::runtime_error("invalid response from tracker"); + if (i->type() != entry::string_t || i->string().length() != 20) + { + fail(-1, "invalid response from tracker (invalid peer id)"); + return false; + } std::copy(i->string().begin(), i->string().end(), ret.pid.begin()); } else @@ -873,132 +272,167 @@ namespace libtorrent // extract ip i = info.find_key("ip"); - if (i == 0) throw std::runtime_error("invalid response from tracker"); + if (i == 0 || i->type() != entry::string_t) + { + fail(-1, "invalid response from tracker"); + return false; + } ret.ip = i->string(); // extract port i = info.find_key("port"); - if (i == 0) throw std::runtime_error("invalid response from tracker"); + if (i == 0 || i->type() != entry::int_t) + { + fail(-1, "invalid response from tracker"); + return false; + } ret.port = (unsigned short)i->integer(); - return ret; + return true; } - void http_tracker_connection::parse(entry const& e) + void http_tracker_connection::parse(int status_code, entry const& e) { boost::shared_ptr cb = requester(); if (!cb) return; - try + // parse the response + entry const* failure = e.find_key("failure reason"); + if (failure && failure->type() == entry::string_t) { - // parse the response - try - { - entry const& failure = e["failure reason"]; + fail(status_code, failure->string().c_str()); + return; + } - fail(m_parser.status_code(), failure.string().c_str()); + entry const* warning = e.find_key("warning message"); + if (warning && warning->type() == entry::string_t) + { + cb->tracker_warning(tracker_req(), warning->string()); + } + + std::vector peer_list; + + if (tracker_req().kind == tracker_request::scrape_request) + { + std::string ih = tracker_req().info_hash.to_string(); + + entry const* files = e.find_key("files"); + if (files == 0 || files->type() != entry::dictionary_t) + { + fail(-1, "invalid or missing 'files' entry in scrape response"); return; } - catch (type_error const&) {} - try + entry const* scrape_data = files->find_key(ih); + if (scrape_data == 0 || scrape_data->type() != entry::dictionary_t) { - entry const& warning = e["warning message"]; - cb->tracker_warning(warning.string()); + fail(-1, "missing or invalid info-hash entry in scrape response"); + return; } - catch(type_error const&) {} - - if (tracker_req().kind == tracker_request::scrape_request) + entry const* complete = scrape_data->find_key("complete"); + entry const* incomplete = scrape_data->find_key("incomplete"); + entry const* downloaded = scrape_data->find_key("downloaded"); + if (complete == 0 || incomplete == 0 || downloaded == 0 + || complete->type() != entry::int_t + || incomplete->type() != entry::int_t + || downloaded->type() != entry::int_t) { - std::string ih = tracker_req().info_hash.to_string(); - entry scrape_data = e["files"][ih]; + fail(-1, "missing 'complete' or 'incomplete' entries in scrape response"); + return; + } + cb->tracker_scrape_response(tracker_req(), int(complete->integer()) + , int(incomplete->integer()), int(downloaded->integer())); + return; + } - int complete = -1; - int incomplete = -1; - int downloaded = -1; + entry const* interval = e.find_key("interval"); + if (interval == 0 || interval->type() != entry::int_t) + { + fail(-1, "missing or invalid 'interval' entry in tracker response"); + return; + } - entry const* complete_ent = scrape_data.find_key("complete"); - if (complete_ent && complete_ent->type() == entry::int_t) - complete = int(complete_ent->integer()); + entry const* peers_ent = e.find_key("peers"); + if (peers_ent == 0) + { + fail(-1, "missing 'peers' entry in tracker response"); + return; + } + + if (peers_ent->type() == entry::string_t) + { + std::string const& peers = peers_ent->string(); + for (std::string::const_iterator i = peers.begin(); + i != peers.end();) + { + if (std::distance(i, peers.end()) < 6) break; + + peer_entry p; + p.pid.clear(); + p.ip = detail::read_v4_address(i).to_string(); + p.port = detail::read_uint16(i); + peer_list.push_back(p); + } + } + else if (peers_ent->type() == entry::list_t) + { + entry::list_type const& l = peers_ent->list(); + for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i) + { + peer_entry p; + if (!extract_peer_info(*i, p)) return; + peer_list.push_back(p); + } + } + else + { + fail(-1, "invalid 'peers' entry in tracker response"); + return; + } + + entry const* ipv6_peers = e.find_key("peers6"); + if (ipv6_peers && ipv6_peers->type() == entry::string_t) + { + std::string const& peers = ipv6_peers->string(); + for (std::string::const_iterator i = peers.begin(); + i != peers.end();) + { + if (std::distance(i, peers.end()) < 18) break; + + peer_entry p; + p.pid.clear(); + p.ip = detail::read_v6_address(i).to_string(); + p.port = detail::read_uint16(i); + peer_list.push_back(p); + } + } + + // look for optional scrape info + int complete = -1; + int incomplete = -1; + address external_ip; + + entry const* ip_ent = e.find_key("external ip"); + if (ip_ent && ip_ent->type() == entry::string_t) + { + std::string const& ip = ip_ent->string(); + char const* p = &ip[0]; + if (ip.size() == address_v4::bytes_type::static_size) + external_ip = detail::read_v4_address(p); + else if (ip.size() == address_v6::bytes_type::static_size) + external_ip = detail::read_v6_address(p); + } - entry const* incomplete_ent = scrape_data.find_key("incomplete"); - if (incomplete_ent && incomplete_ent->type() == entry::int_t) - incomplete = int(incomplete_ent->integer()); + entry const* complete_ent = e.find_key("complete"); + if (complete_ent && complete_ent->type() == entry::int_t) + complete = int(complete_ent->integer()); - entry const* downloaded_ent = scrape_data.find_key("downloaded"); - if (downloaded_ent && downloaded_ent->type() == entry::int_t) - downloaded = int(downloaded_ent->integer()); + entry const* incomplete_ent = e.find_key("incomplete"); + if (incomplete_ent && incomplete_ent->type() == entry::int_t) + incomplete = int(incomplete_ent->integer()); - cb->tracker_scrape_response(tracker_req(), complete - , incomplete, downloaded); - return; - } - - std::vector peer_list; - int interval = (int)e["interval"].integer(); - - if (e["peers"].type() == entry::string_t) - { - std::string const& peers = e["peers"].string(); - for (std::string::const_iterator i = peers.begin(); - i != peers.end();) - { - if (std::distance(i, peers.end()) < 6) break; - - peer_entry p; - p.pid.clear(); - p.ip = detail::read_v4_address(i).to_string(); - p.port = detail::read_uint16(i); - peer_list.push_back(p); - } - } - else - { - entry::list_type const& l = e["peers"].list(); - for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i) - { - peer_entry p = extract_peer_info(*i); - peer_list.push_back(p); - } - } - - if (entry const* ipv6_peers = e.find_key("peers6")) - { - std::string const& peers = ipv6_peers->string(); - for (std::string::const_iterator i = peers.begin(); - i != peers.end();) - { - if (std::distance(i, peers.end()) < 18) break; - - peer_entry p; - p.pid.clear(); - p.ip = detail::read_v6_address(i).to_string(); - p.port = detail::read_uint16(i); - peer_list.push_back(p); - } - } - - // look for optional scrape info - int complete = -1; - int incomplete = -1; - - try { complete = int(e["complete"].integer()); } - catch(type_error&) {} - - try { incomplete = int(e["incomplete"].integer()); } - catch(type_error&) {} - - cb->tracker_response(tracker_req(), peer_list, interval, complete - , incomplete); - } - catch(type_error& e) - { - cb->tracker_request_error(tracker_req(), m_parser.status_code(), e.what()); - } - catch(std::runtime_error& e) - { - cb->tracker_request_error(tracker_req(), m_parser.status_code(), e.what()); - } + cb->tracker_response(tracker_req(), peer_list, interval->integer(), complete + , incomplete, external_ip); } } diff --git a/libtorrent/src/instantiate_connection.cpp b/libtorrent/src/instantiate_connection.cpp index 23a202da4..776ab6a12 100644 --- a/libtorrent/src/instantiate_connection.cpp +++ b/libtorrent/src/instantiate_connection.cpp @@ -37,12 +37,11 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket_type.hpp" #include #include -#include namespace libtorrent { - bool instantiate_connection(asio::io_service& ios + bool instantiate_connection(io_service& ios , proxy_settings const& ps, socket_type& s) { if (ps.type == proxy_settings::none) diff --git a/libtorrent/src/kademlia/closest_nodes.cpp b/libtorrent/src/kademlia/closest_nodes.cpp index 7e24182de..859170f7f 100644 --- a/libtorrent/src/kademlia/closest_nodes.cpp +++ b/libtorrent/src/kademlia/closest_nodes.cpp @@ -40,8 +40,6 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { namespace dht { -using asio::ip::udp; - closest_nodes_observer::~closest_nodes_observer() { if (m_algorithm) m_algorithm->failed(m_self, true); @@ -100,6 +98,7 @@ closest_nodes::closest_nodes( void closest_nodes::invoke(node_id const& id, udp::endpoint addr) { + TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(closest_nodes_observer)); observer_ptr o(new (m_rpc.allocator().malloc()) closest_nodes_observer(this, id, m_target)); #ifndef NDEBUG o->m_in_constructor = false; diff --git a/libtorrent/src/kademlia/dht_tracker.cpp b/libtorrent/src/kademlia/dht_tracker.cpp index 56bc765de..4c781b9e7 100644 --- a/libtorrent/src/kademlia/dht_tracker.cpp +++ b/libtorrent/src/kademlia/dht_tracker.cpp @@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/bencode.hpp" #include "libtorrent/io.hpp" #include "libtorrent/version.hpp" +#include "libtorrent/escape_string.hpp" using boost::ref; using boost::lexical_cast; @@ -58,7 +59,6 @@ using libtorrent::dht::node_impl; using libtorrent::dht::node_id; using libtorrent::dht::packet_t; using libtorrent::dht::msg; -using libtorrent::dht::packet_iterator; namespace messages = libtorrent::dht::messages; using namespace libtorrent::detail; @@ -67,9 +67,6 @@ enum key_refresh = 5 // generate a new write token key every 5 minutes }; -using asio::ip::udp; -typedef asio::ip::address_v4 address; - namespace { const int tick_period = 1; // minutes @@ -145,27 +142,23 @@ namespace libtorrent { namespace dht // class that puts the networking and the kademlia node in a single // unit and connecting them together. - dht_tracker::dht_tracker(asio::io_service& ios, dht_settings const& settings - , asio::ip::address listen_interface, entry const& bootstrap) - : m_strand(ios) - , m_socket(ios, udp::endpoint(listen_interface, settings.service_port)) - , m_dht(bind(&dht_tracker::send_packet, this, _1), settings + dht_tracker::dht_tracker(udp_socket& sock, dht_settings const& settings + , entry const& bootstrap) + : m_dht(bind(&dht_tracker::send_packet, this, _1), settings , read_id(bootstrap)) - , m_buffer(0) + , m_sock(sock) , m_last_new_key(time_now() - minutes(key_refresh)) - , m_timer(ios) - , m_connection_timer(ios) - , m_refresh_timer(ios) + , m_timer(sock.get_io_service()) + , m_connection_timer(sock.get_io_service()) + , m_refresh_timer(sock.get_io_service()) , m_settings(settings) , m_refresh_bucket(160) , m_abort(false) - , m_host_resolver(ios) + , m_host_resolver(sock.get_io_service()) , m_refs(0) { using boost::bind; - m_in_buf[0].resize(1000); - m_in_buf[1].resize(1000); #ifdef TORRENT_DHT_VERBOSE_LOGGING m_counter = 0; std::fill_n(m_replies_bytes_sent, 5, 0); @@ -203,18 +196,15 @@ namespace libtorrent { namespace dht } catch (std::exception&) {} } - m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0] - , m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer] - , m_strand.wrap(bind(&dht_tracker::on_receive, self(), _1, _2))); m_timer.expires_from_now(seconds(1)); - m_timer.async_wait(m_strand.wrap(bind(&dht_tracker::tick, self(), _1))); + m_timer.async_wait(bind(&dht_tracker::tick, self(), _1)); m_connection_timer.expires_from_now(seconds(10)); - m_connection_timer.async_wait(m_strand.wrap( - bind(&dht_tracker::connection_timeout, self(), _1))); + m_connection_timer.async_wait( + bind(&dht_tracker::connection_timeout, self(), _1)); m_refresh_timer.expires_from_now(seconds(5)); - m_refresh_timer.async_wait(m_strand.wrap(bind(&dht_tracker::refresh_timeout, self(), _1))); + m_refresh_timer.async_wait(bind(&dht_tracker::refresh_timeout, self(), _1)); m_dht.bootstrap(initial_nodes, bind(&dht_tracker::on_bootstrap, self())); } @@ -226,7 +216,6 @@ namespace libtorrent { namespace dht m_timer.cancel(); m_connection_timer.cancel(); m_refresh_timer.cancel(); - m_socket.close(); m_host_resolver.cancel(); } @@ -237,16 +226,15 @@ namespace libtorrent { namespace dht s.dht_global_nodes = m_dht.num_global_nodes(); } - void dht_tracker::connection_timeout(asio::error_code const& e) + void dht_tracker::connection_timeout(error_code const& e) try { mutex_t::scoped_lock l(m_mutex); if (e || m_abort) return; - if (!m_socket.is_open()) return; time_duration d = m_dht.connection_timeout(); m_connection_timer.expires_from_now(d); - m_connection_timer.async_wait(m_strand.wrap(bind(&dht_tracker::connection_timeout, self(), _1))); + m_connection_timer.async_wait(bind(&dht_tracker::connection_timeout, self(), _1)); } catch (std::exception& exc) { @@ -257,43 +245,30 @@ namespace libtorrent { namespace dht #endif }; - void dht_tracker::refresh_timeout(asio::error_code const& e) + void dht_tracker::refresh_timeout(error_code const& e) try { mutex_t::scoped_lock l(m_mutex); if (e || m_abort) return; - if (!m_socket.is_open()) return; time_duration d = m_dht.refresh_timeout(); m_refresh_timer.expires_from_now(d); - m_refresh_timer.async_wait(m_strand.wrap( - bind(&dht_tracker::refresh_timeout, self(), _1))); + m_refresh_timer.async_wait( + bind(&dht_tracker::refresh_timeout, self(), _1)); } catch (std::exception&) { TORRENT_ASSERT(false); }; - void dht_tracker::rebind(asio::ip::address listen_interface, int listen_port) - { - m_socket.close(); - udp::endpoint ep(listen_interface, listen_port); - m_socket.open(ep.protocol()); - m_socket.bind(ep); - m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0] - , m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer] - , m_strand.wrap(bind(&dht_tracker::on_receive, self(), _1, _2))); - } - - void dht_tracker::tick(asio::error_code const& e) + void dht_tracker::tick(error_code const& e) try { mutex_t::scoped_lock l(m_mutex); if (e || m_abort) return; - if (!m_socket.is_open()) return; m_timer.expires_from_now(minutes(tick_period)); - m_timer.async_wait(m_strand.wrap(bind(&dht_tracker::tick, self(), _1))); + m_timer.async_wait(bind(&dht_tracker::tick, self(), _1)); ptime now = time_now(); if (now - m_last_new_key > minutes(key_refresh)) @@ -398,28 +373,23 @@ namespace libtorrent { namespace dht m_dht.announce(ih, listen_port, f); } + + void dht_tracker::on_unreachable(udp::endpoint const& ep) + { + m_dht.unreachable(ep); + } + // translate bittorrent kademlia message into the generice kademlia message // used by the library - void dht_tracker::on_receive(asio::error_code const& error, size_t bytes_transferred) + void dht_tracker::on_receive(udp::endpoint const& ep, char const* buf, int bytes_transferred) try { - if (error == asio::error::operation_aborted) return; - if (!m_socket.is_open()) return; - - int current_buffer = m_buffer; - m_buffer = (m_buffer + 1) & 1; - m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0] - , m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer] - , m_strand.wrap(bind(&dht_tracker::on_receive, self(), _1, _2))); - - if (error) return; - node_ban_entry* match = 0; node_ban_entry* min = m_ban_nodes; ptime now = time_now(); for (node_ban_entry* i = m_ban_nodes; i < m_ban_nodes + num_ban_nodes; ++i) { - if (i->src == m_remote_endpoint[current_buffer]) + if (i->src == ep) { match = i; break; @@ -438,9 +408,8 @@ namespace libtorrent { namespace dht if (match->count == 20) { TORRENT_LOG(dht_tracker) << time_now_string() << " BANNING PEER [ ip: " - << m_remote_endpoint[current_buffer] << " | " - "time: " << total_seconds((now - match->limit) + seconds(5)) - << " | count: " << match->count << " ]"; + << ep << " time: " << total_milliseconds((now - match->limit) + seconds(5)) / 1000.f + << " count: " << match->count << " ]"; } #endif // we've received 20 messages in less than 5 seconds from @@ -459,7 +428,7 @@ namespace libtorrent { namespace dht { min->count = 1; min->limit = now + seconds(5); - min->src = m_remote_endpoint[current_buffer]; + min->src = ep; } #ifdef TORRENT_DHT_VERBOSE_LOGGING @@ -474,17 +443,26 @@ namespace libtorrent { namespace dht TORRENT_ASSERT(bytes_transferred > 0); - entry e = bdecode(m_in_buf[current_buffer].begin() - , m_in_buf[current_buffer].end()); + entry e = bdecode(buf, buf + bytes_transferred); + if (e.type() == entry::undefined_t) + { +#ifdef TORRENT_DHT_VERBOSE_LOGGING + std::string msg(buf, buf + bytes_transferred); + TORRENT_LOG(dht_tracker) << "invalid incoming packet: " + << e.what() << "\n" << msg << "\n"; +#endif + return; + } #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << time_now_string() << " RECEIVED [" - << m_remote_endpoint[current_buffer] << "]:"; + std::stringstream log_line; + log_line << time_now_string() << " RECEIVED [" + " ip: " << ep; #endif libtorrent::dht::msg m; m.message_id = 0; - m.addr = m_remote_endpoint[current_buffer]; + m.addr = ep; m.transaction_id = e["t"].string(); #ifdef TORRENT_DHT_VERBOSE_LOGGING @@ -497,36 +475,36 @@ namespace libtorrent { namespace dht if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "UT")) { ++m_ut_message_input; - TORRENT_LOG(dht_tracker) << " client: uTorrent"; + log_line << " c: uTorrent"; } else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "LT")) { ++m_lt_message_input; - TORRENT_LOG(dht_tracker) << " client: libtorrent"; + log_line << " c: libtorrent"; } else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MP")) { ++m_mp_message_input; - TORRENT_LOG(dht_tracker) << " client: MooPolice"; + log_line << " c: MooPolice"; } else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "GR")) { ++m_gr_message_input; - TORRENT_LOG(dht_tracker) << " client: GetRight"; + log_line << " c: GetRight"; } else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MO")) { ++m_mo_message_input; - TORRENT_LOG(dht_tracker) << " client: Mono Torrent"; + log_line << " c: Mono Torrent"; } else { - TORRENT_LOG(dht_tracker) << " client: " << client; + log_line << " c: " << client; } } catch (std::exception&) { - TORRENT_LOG(dht_tracker) << " client: generic"; + log_line << " c: generic"; }; #endif @@ -535,8 +513,8 @@ namespace libtorrent { namespace dht if (msg_type == "r") { #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " reply: transaction: " - << m.transaction_id; + log_line << " r: " << messages::ids[m.message_id] + << " t: " << to_hex(m.transaction_id); #endif m.reply = true; @@ -564,7 +542,7 @@ namespace libtorrent { namespace dht read_endpoint_list(n, m.peers); } #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " peers: " << m.peers.size(); + log_line << " p: " << m.peers.size(); #endif } @@ -584,7 +562,7 @@ namespace libtorrent { namespace dht id, read_v4_endpoint(i))); } #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " nodes: " << m.nodes.size(); + log_line << " n: " << m.nodes.size(); #endif } @@ -609,7 +587,7 @@ namespace libtorrent { namespace dht id, read_v6_endpoint(in))); } #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " nodes2 + nodes: " << m.nodes.size(); + log_line << " n2: " << m.nodes.size(); #endif } @@ -626,7 +604,7 @@ namespace libtorrent { namespace dht std::string request_kind(e["q"].string()); #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " query: " << request_kind; + log_line << " q: " << request_kind; #endif if (request_kind == "ping") @@ -639,8 +617,7 @@ namespace libtorrent { namespace dht if (target.size() != 20) throw std::runtime_error("invalid size of target id"); std::copy(target.begin(), target.end(), m.info_hash.begin()); #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " target: " - << boost::lexical_cast(m.info_hash); + log_line << " t: " << boost::lexical_cast(m.info_hash); #endif m.message_id = libtorrent::dht::messages::find_node; @@ -652,8 +629,7 @@ namespace libtorrent { namespace dht std::copy(info_hash.begin(), info_hash.end(), m.info_hash.begin()); m.message_id = libtorrent::dht::messages::get_peers; #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " info_hash: " - << boost::lexical_cast(m.info_hash); + log_line << " ih: " << boost::lexical_cast(m.info_hash); #endif } else if (request_kind == "announce_peer") @@ -669,9 +645,8 @@ namespace libtorrent { namespace dht m.write_token = a["token"]; m.message_id = libtorrent::dht::messages::announce_peer; #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " info_hash: " - << boost::lexical_cast(m.info_hash); - TORRENT_LOG(dht_tracker) << " port: " << m.port; + log_line << " ih: " << boost::lexical_cast(m.info_hash); + log_line << " p: " << m.port; if (!m_dht.verify_token(m)) ++m_failed_announces; @@ -693,8 +668,8 @@ namespace libtorrent { namespace dht m.error_msg = list.back().string(); m.error_code = list.front().integer(); #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " incoming error: " << m.error_code << " " - << m.error_msg; + log_line << " incoming error: " << m.error_code + << " " << m.error_msg; #endif throw std::runtime_error("DHT error message"); } @@ -713,7 +688,7 @@ namespace libtorrent { namespace dht ++m_queries_received[m.message_id]; m_queries_bytes_received[m.message_id] += int(bytes_transferred); } - TORRENT_LOG(dht_tracker) << e; + TORRENT_LOG(dht_tracker) << log_line.str() << " ]"; #endif TORRENT_ASSERT(m.message_id != messages::error); m_dht.incoming(m); @@ -721,9 +696,7 @@ namespace libtorrent { namespace dht catch (std::exception& e) { #ifdef TORRENT_DHT_VERBOSE_LOGGING - int current_buffer = (m_buffer + 1) & 1; - std::string msg(m_in_buf[current_buffer].begin() - , m_in_buf[current_buffer].begin() + bytes_transferred); + std::string msg(buf, buf + bytes_transferred); TORRENT_LOG(dht_tracker) << "invalid incoming packet: " << e.what() << "\n" << msg << "\n"; #endif @@ -773,15 +746,14 @@ namespace libtorrent { namespace dht void dht_tracker::add_node(std::pair const& node) { udp::resolver::query q(node.first, lexical_cast(node.second)); - m_host_resolver.async_resolve(q, m_strand.wrap( - bind(&dht_tracker::on_name_lookup, self(), _1, _2))); + m_host_resolver.async_resolve(q, + bind(&dht_tracker::on_name_lookup, self(), _1, _2)); } - void dht_tracker::on_name_lookup(asio::error_code const& e + void dht_tracker::on_name_lookup(error_code const& e , udp::resolver::iterator host) try { if (e || host == udp::resolver::iterator()) return; - if (!m_socket.is_open()) return; add_node(host->endpoint()); } catch (std::exception&) @@ -792,15 +764,14 @@ namespace libtorrent { namespace dht void dht_tracker::add_router_node(std::pair const& node) { udp::resolver::query q(node.first, lexical_cast(node.second)); - m_host_resolver.async_resolve(q, m_strand.wrap( - bind(&dht_tracker::on_router_name_lookup, self(), _1, _2))); + m_host_resolver.async_resolve(q, + bind(&dht_tracker::on_router_name_lookup, self(), _1, _2)); } - void dht_tracker::on_router_name_lookup(asio::error_code const& e + void dht_tracker::on_router_name_lookup(error_code const& e , udp::resolver::iterator host) try { if (e || host == udp::resolver::iterator()) return; - if (!m_socket.is_open()) return; m_dht.add_router_node(host->endpoint()); } catch (std::exception&) @@ -849,9 +820,6 @@ namespace libtorrent { namespace dht p.list().push_back(entry(endpoint)); } } -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " nodes: " << m.nodes.size(); -#endif } } @@ -868,9 +836,10 @@ namespace libtorrent { namespace dht e["v"] = std::string(version_str, version_str + 4); #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << time_now_string() - << " SENDING [" << m.addr << "]:"; - TORRENT_LOG(dht_tracker) << " transaction: " << m.transaction_id; + std::stringstream log_line; + log_line << time_now_string() + << " SENDING [ ip: " << m.addr + << " t: " << to_hex(m.transaction_id); #endif if (m.message_id == messages::error) @@ -883,8 +852,8 @@ namespace libtorrent { namespace dht error_list.list().push_back(entry(m.error_msg)); e["e"] = error_list; #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << time_now_string() - << " outgoing error: " << m.error_code << " " << m.error_msg; + log_line << " err: " << m.error_code + << " msg: " << m.error_msg; #endif } else if (m.reply) @@ -895,8 +864,7 @@ namespace libtorrent { namespace dht r["id"] = std::string(m.id.begin(), m.id.end()); #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << time_now_string() - << " reply: " << messages::ids[m.message_id]; + log_line << " r: " << messages::ids[m.message_id]; #endif if (m.write_token.type() != entry::undefined_t) @@ -932,7 +900,7 @@ namespace libtorrent { namespace dht p.list().push_back(entry(endpoint)); } #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " peers: " << m.peers.size(); + log_line << " p: " << m.peers.size(); #endif } break; @@ -956,8 +924,7 @@ namespace libtorrent { namespace dht e["q"] = messages::ids[m.message_id]; #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " query: " - << messages::ids[m.message_id]; + log_line << " q: " << messages::ids[m.message_id]; #endif switch (m.message_id) @@ -966,8 +933,7 @@ namespace libtorrent { namespace dht { a["target"] = std::string(m.info_hash.begin(), m.info_hash.end()); #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " target: " - << boost::lexical_cast(m.info_hash); + log_line << " target: " << boost::lexical_cast(m.info_hash); #endif break; } @@ -975,8 +941,7 @@ namespace libtorrent { namespace dht { a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end()); #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " info_hash: " - << boost::lexical_cast(m.info_hash); + log_line << " ih: " << boost::lexical_cast(m.info_hash); #endif break; } @@ -985,9 +950,8 @@ namespace libtorrent { namespace dht a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end()); a["token"] = m.write_token; #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) - << " port: " << m.port - << " info_hash: " << boost::lexical_cast(m.info_hash); + log_line << " p: " << m.port + << " ih: " << boost::lexical_cast(m.info_hash); #endif break; default: break; @@ -997,10 +961,8 @@ namespace libtorrent { namespace dht m_send_buf.clear(); bencode(std::back_inserter(m_send_buf), e); - asio::error_code ec; - m_socket.send_to(asio::buffer(&m_send_buf[0] - , (int)m_send_buf.size()), m.addr, 0, ec); - if (ec) return; + error_code ec; + m_sock.send(m.addr, &m_send_buf[0], (int)m_send_buf.size(), ec); #ifdef TORRENT_DHT_VERBOSE_LOGGING m_total_out_bytes += m_send_buf.size(); @@ -1014,7 +976,7 @@ namespace libtorrent { namespace dht { m_queries_out_bytes += m_send_buf.size(); } - TORRENT_LOG(dht_tracker) << e; + TORRENT_LOG(dht_tracker) << log_line.str() << " ]"; #endif if (!m.piggy_backed_ping) return; diff --git a/libtorrent/src/kademlia/find_data.cpp b/libtorrent/src/kademlia/find_data.cpp index 9dc161888..8da689d68 100644 --- a/libtorrent/src/kademlia/find_data.cpp +++ b/libtorrent/src/kademlia/find_data.cpp @@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include namespace libtorrent { namespace dht { @@ -101,7 +102,7 @@ find_data::find_data( add_requests(); } -void find_data::invoke(node_id const& id, asio::ip::udp::endpoint addr) +void find_data::invoke(node_id const& id, udp::endpoint addr) { if (m_done) { @@ -109,6 +110,7 @@ void find_data::invoke(node_id const& id, asio::ip::udp::endpoint addr) return; } + TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(find_data_observer)); observer_ptr o(new (m_rpc.allocator().malloc()) find_data_observer(this, id, m_target)); #ifndef NDEBUG o->m_in_constructor = false; diff --git a/libtorrent/src/kademlia/node.cpp b/libtorrent/src/kademlia/node.cpp index 60811909f..63a8ac84b 100644 --- a/libtorrent/src/kademlia/node.cpp +++ b/libtorrent/src/kademlia/node.cpp @@ -43,7 +43,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/random_sample.hpp" #include "libtorrent/kademlia/node_id.hpp" #include "libtorrent/kademlia/rpc_manager.hpp" -#include "libtorrent/kademlia/packet_iterator.hpp" #include "libtorrent/kademlia/routing_table.hpp" #include "libtorrent/kademlia/node.hpp" @@ -66,8 +65,6 @@ namespace // TODO: configurable? enum { announce_interval = 30 }; -using asio::ip::udp; - #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_DEFINE_LOG(node) #endif @@ -246,6 +243,11 @@ void node_impl::refresh_bucket(int bucket) try } catch (std::exception&) {} +void node_impl::unreachable(udp::endpoint const& ep) +{ + m_rpc.unreachable(ep); +} + void node_impl::incoming(msg const& m) { if (m_rpc.incoming(m)) @@ -270,6 +272,9 @@ namespace for (std::vector::const_iterator i = v.begin() , end(v.end()); i != end; ++i) { +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(node) << " distance: " << (160 - distance_exp(ih, i->id)); +#endif observer_ptr o(new (rpc.allocator().malloc()) get_peers_observer(ih, listen_port, rpc, f)); #ifndef NDEBUG o->m_in_constructor = false; diff --git a/libtorrent/src/kademlia/refresh.cpp b/libtorrent/src/kademlia/refresh.cpp index 916b6d06a..1c5978893 100644 --- a/libtorrent/src/kademlia/refresh.cpp +++ b/libtorrent/src/kademlia/refresh.cpp @@ -47,8 +47,6 @@ using boost::bind; namespace libtorrent { namespace dht { -using asio::ip::udp; - #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_DEFINE_LOG(refresh) #endif @@ -103,6 +101,7 @@ void ping_observer::timeout() void refresh::invoke(node_id const& nid, udp::endpoint addr) { + TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(refresh_observer)); observer_ptr o(new (m_rpc.allocator().malloc()) refresh_observer( this, nid, m_target)); #ifndef NDEBUG @@ -157,6 +156,7 @@ void refresh::invoke_pings_or_finish(bool prevent_request) try { + TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(ping_observer)); observer_ptr o(new (m_rpc.allocator().malloc()) ping_observer( this, node.id)); #ifndef NDEBUG diff --git a/libtorrent/src/kademlia/routing_table.cpp b/libtorrent/src/kademlia/routing_table.cpp index 6faeb6f50..6c4d93f2b 100644 --- a/libtorrent/src/kademlia/routing_table.cpp +++ b/libtorrent/src/kademlia/routing_table.cpp @@ -50,8 +50,9 @@ using boost::uint8_t; namespace libtorrent { namespace dht { -using asio::ip::udp; -typedef asio::ip::address_v4 address; +#ifdef TORRENT_DHT_VERBOSE_LOGGING +TORRENT_DEFINE_LOG(table) +#endif routing_table::routing_table(node_id const& id, int bucket_size , dht_settings const& settings) @@ -225,6 +226,15 @@ void routing_table::node_failed(node_id const& id) if (rb.empty()) { ++i->fail_count; + +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(table) << " NODE FAILED" + " id: " << id << + " ip: " << i->addr << + " fails: " << i->fail_count << + " up-time: " << total_seconds(time_now() - i->first_seen); +#endif + if (i->fail_count >= m_settings.max_fail_count) { b.erase(i); @@ -355,6 +365,19 @@ bool routing_table::need_bootstrap() const return true; } +template +DstIter copy_if_n(SrcIter begin, SrcIter end, DstIter target, size_t n, Pred p) +{ + for (; n > 0 && begin != end; ++begin) + { + if (!p(*begin)) continue; + *target = *begin; + --n; + ++target; + } + return target; +} + // fills the vector with the k nodes from our buckets that // are nearest to the given id. void routing_table::find_node(node_id const& target @@ -369,8 +392,8 @@ void routing_table::find_node(node_id const& target // copy all nodes that hasn't failed into the target // vector. - std::remove_copy_if(b.begin(), b.end(), std::back_inserter(l) - , bind(&node_entry::fail_count, _1)); + copy_if_n(b.begin(), b.end(), std::back_inserter(l) + , (std::min)(size_t(count), b.size()), bind(&node_entry::fail_count, _1) == 0); TORRENT_ASSERT((int)l.size() <= count); if ((int)l.size() == count) @@ -393,19 +416,23 @@ void routing_table::find_node(node_id const& target , bind(&node_entry::fail_count, _1)); } - std::random_shuffle(tmpb.begin(), tmpb.end()); - size_t to_copy = (std::min)(m_bucket_size - l.size() - , tmpb.size()); - std::copy(tmpb.begin(), tmpb.begin() + to_copy - , std::back_inserter(l)); + if (count - l.size() < tmpb.size()) + { + std::random_shuffle(tmpb.begin(), tmpb.end()); + size_t to_copy = count - l.size(); + std::copy(tmpb.begin(), tmpb.begin() + to_copy, std::back_inserter(l)); + } + else + { + std::copy(tmpb.begin(), tmpb.end(), std::back_inserter(l)); + } - TORRENT_ASSERT((int)l.size() <= m_bucket_size); + TORRENT_ASSERT((int)l.size() <= count); // return if we have enough nodes or if the bucket index // is the biggest index available (there are no more buckets) // to look in. - if ((int)l.size() == count - || bucket_index == (int)m_buckets.size() - 1) + if ((int)l.size() == count) { TORRENT_ASSERT(std::count_if(l.begin(), l.end() , boost::bind(&node_entry::fail_count, _1) != 0) == 0); @@ -416,18 +443,17 @@ void routing_table::find_node(node_id const& target { bucket_t& b = m_buckets[i].first; - std::remove_copy_if(b.begin(), b.end(), std::back_inserter(l) - , bind(&node_entry::fail_count, _1)); - if ((int)l.size() >= count) + size_t to_copy = (std::min)(count - l.size(), b.size()); + copy_if_n(b.begin(), b.end(), std::back_inserter(l) + , to_copy, bind(&node_entry::fail_count, _1) == 0); + TORRENT_ASSERT((int)l.size() <= count); + if ((int)l.size() == count) { - l.erase(l.begin() + count, l.end()); TORRENT_ASSERT(std::count_if(l.begin(), l.end() , boost::bind(&node_entry::fail_count, _1) != 0) == 0); return; } } - TORRENT_ASSERT((int)l.size() == count - || std::distance(l.begin(), l.end()) < m_bucket_size); TORRENT_ASSERT((int)l.size() <= count); TORRENT_ASSERT(std::count_if(l.begin(), l.end() diff --git a/libtorrent/src/kademlia/rpc_manager.cpp b/libtorrent/src/kademlia/rpc_manager.cpp index 7295cf0bf..384be2eed 100644 --- a/libtorrent/src/kademlia/rpc_manager.cpp +++ b/libtorrent/src/kademlia/rpc_manager.cpp @@ -121,6 +121,7 @@ rpc_manager::rpc_manager(fun const& f, node_id const& our_id rpc_manager::~rpc_manager() { + TORRENT_ASSERT(!m_destructing); m_destructing = true; #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(rpc) << "Destructing"; @@ -136,6 +137,12 @@ rpc_manager::~rpc_manager() } #ifndef NDEBUG +size_t rpc_manager::allocation_size() const +{ + size_t s = sizeof(mpl::deref::type); + return s; +} + void rpc_manager::check_invariant() const { TORRENT_ASSERT(m_oldest_transaction_id >= 0); @@ -152,6 +159,39 @@ void rpc_manager::check_invariant() const } #endif +void rpc_manager::unreachable(udp::endpoint const& ep) +{ +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(rpc) << time_now_string() << " PORT_UNREACHABLE [ ip: " << ep << " ]"; +#endif + int num_active = m_oldest_transaction_id < m_next_transaction_id + ? m_next_transaction_id - m_oldest_transaction_id + : max_transactions - m_next_transaction_id + m_oldest_transaction_id; + TORRENT_ASSERT((m_oldest_transaction_id + num_active) % max_transactions + == m_next_transaction_id); + int tid = m_oldest_transaction_id; + for (int i = 0; i < num_active; ++i, ++tid) + { + if (tid >= max_transactions) tid = 0; + observer_ptr const& o = m_transactions[tid]; + if (!o) continue; + if (o->target_addr != ep) continue; + observer_ptr ptr = m_transactions[tid]; + m_transactions[tid] = 0; + if (tid == m_oldest_transaction_id) + { + ++m_oldest_transaction_id; + if (m_oldest_transaction_id >= max_transactions) + m_oldest_transaction_id = 0; + } +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(rpc) << " found transaction [ tid: " << tid << " ]"; +#endif + ptr->timeout(); + return; + } +} + bool rpc_manager::incoming(msg const& m) { INVARIANT_CHECK; @@ -302,7 +342,7 @@ time_duration rpc_manager::tick() // clear the aborted transactions, will likely // generate new requests. We need to swap, since the // destrutors may add more observers to the m_aborted_transactions - std::vector().swap(m_aborted_transactions); + std::vector().swap(m_aborted_transactions); return milliseconds(timeout_ms); } @@ -429,6 +469,7 @@ void rpc_manager::reply_with_ping(msg& m) std::back_insert_iterator out(m.ping_transaction_id); io::write_uint16(m_next_transaction_id, out); + TORRENT_ASSERT(allocation_size() >= sizeof(null_observer)); observer_ptr o(new (allocator().malloc()) null_observer(allocator())); #ifndef NDEBUG o->m_in_constructor = false; diff --git a/libtorrent/src/kademlia/traversal_algorithm.cpp b/libtorrent/src/kademlia/traversal_algorithm.cpp index b1e803354..138d42905 100644 --- a/libtorrent/src/kademlia/traversal_algorithm.cpp +++ b/libtorrent/src/kademlia/traversal_algorithm.cpp @@ -39,7 +39,6 @@ POSSIBILITY OF SUCH DAMAGE. #include using boost::bind; -using asio::ip::udp; namespace libtorrent { namespace dht { @@ -89,7 +88,8 @@ boost::pool<>& traversal_algorithm::allocator() const void traversal_algorithm::traverse(node_id const& id, udp::endpoint addr) { #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(traversal) << "node returned a list which included a node with id 0"; + if (id.is_all_zeros()) + TORRENT_LOG(traversal) << time_now_string() << " WARNING: node returned a list which included a node with id 0"; #endif add_entry(id, addr, 0); } diff --git a/libtorrent/src/lazy_bdecode.cpp b/libtorrent/src/lazy_bdecode.cpp new file mode 100644 index 000000000..5c1e37419 --- /dev/null +++ b/libtorrent/src/lazy_bdecode.cpp @@ -0,0 +1,425 @@ +/* + +Copyright (c) 2008, Arvid Norberg +All rights reserved. + +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. + +*/ + +#include "libtorrent/lazy_entry.hpp" +#include +#include +#include + +namespace +{ + enum + { + lazy_entry_grow_factor = 3, + lazy_entry_dict_init = 30, + lazy_entry_list_init = 50 + }; +} + +namespace libtorrent +{ + int fail_bdecode() { return -1; } + + // fills in 'val' with what the string between start and the + // first occurance of the delimiter is interpreted as an int. + // return the pointer to the delimiter, or 0 if there is a + // parse error. val should be initialized to zero + char const* parse_int(char const* start, char const* end, char delimiter, boost::int64_t& val) + { + while (start < end && *start != delimiter) + { + using namespace std; + if (!isdigit(*start)) { fail_bdecode(); return 0; } + val *= 10; + val += *start - '0'; + ++start; + } + return start; + } + + char const* find_char(char const* start, char const* end, char delimiter) + { + while (start < end && *start != delimiter) ++start; + return start; + } + + // return 0 = success + int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit) + { + ret.clear(); + if (start == end) return 0; + + std::vector stack; + + stack.push_back(&ret); + while (start < end) + { + if (stack.empty()) break; // done! + + lazy_entry* top = stack.back(); + + if (int(stack.size()) > depth_limit) return fail_bdecode(); + if (start == end) return fail_bdecode(); + char t = *start; + ++start; + if (start == end && t != 'e') return fail_bdecode(); + + switch (top->type()) + { + case lazy_entry::dict_t: + { + if (t == 'e') + { + top->set_end(start); + stack.pop_back(); + continue; + } + boost::int64_t len = t - '0'; + start = parse_int(start, end, ':', len); + if (start == 0 || start + len + 3 > end || *start != ':') return fail_bdecode(); + ++start; + lazy_entry* ent = top->dict_append(start); + start += len; + stack.push_back(ent); + t = *start; + ++start; + break; + } + case lazy_entry::list_t: + { + if (t == 'e') + { + top->set_end(start); + stack.pop_back(); + continue; + } + lazy_entry* ent = top->list_append(); + stack.push_back(ent); + break; + } + default: break; + } + + top = stack.back(); + switch (t) + { + case 'd': + top->construct_dict(start - 1); + continue; + case 'l': + top->construct_list(start - 1); + continue; + case 'i': + { + char const* int_start = start; + start = find_char(start, end, 'e'); + top->construct_int(int_start, start - int_start); + if (start == end) return fail_bdecode(); + TORRENT_ASSERT(*start == 'e'); + ++start; + stack.pop_back(); + continue; + } + default: + { + using namespace std; + if (!isdigit(t)) return fail_bdecode(); + + boost::int64_t len = t - '0'; + start = parse_int(start, end, ':', len); + if (start == 0 || start + len + 1 > end || *start != ':') return fail_bdecode(); + ++start; + top->construct_string(start, int(len)); + stack.pop_back(); + start += len; + continue; + } + } + return 0; + } + return 0; + } + + size_type lazy_entry::int_value() const + { + TORRENT_ASSERT(m_type == int_t); + boost::int64_t val = 0; + bool negative = false; + if (*m_data.start == '-') negative = true; + parse_int(negative?m_data.start+1:m_data.start, m_data.start + m_size, 'e', val); + if (negative) val = -val; + return val; + } + + lazy_entry* lazy_entry::dict_append(char const* name) + { + TORRENT_ASSERT(m_type == dict_t); + TORRENT_ASSERT(m_size <= m_capacity); + if (m_capacity == 0) + { + int capacity = lazy_entry_dict_init; + m_data.dict = new (std::nothrow) std::pair[capacity]; + if (m_data.dict == 0) return 0; + m_capacity = capacity; + } + else if (m_size == m_capacity) + { + int capacity = m_capacity * lazy_entry_grow_factor; + std::pair* tmp = new (std::nothrow) std::pair[capacity]; + if (tmp == 0) return 0; + std::memcpy(tmp, m_data.dict, sizeof(std::pair) * m_size); + for (int i = 0; i < m_size; ++i) m_data.dict[i].second.release(); + delete[] m_data.dict; + m_data.dict = tmp; + m_capacity = capacity; + } + + TORRENT_ASSERT(m_size < m_capacity); + std::pair& ret = m_data.dict[m_size++]; + ret.first = name; + return &ret.second; + } + + namespace + { + // the number of decimal digits needed + // to represent the given value + int num_digits(int val) + { + int ret = 1; + while (val >= 10) + { + ++ret; + val /= 10; + } + return ret; + } + } + + void lazy_entry::construct_string(char const* start, int length) + { + TORRENT_ASSERT(m_type == none_t); + m_type = string_t; + m_data.start = start; + m_size = length; + m_begin = start - 1 - num_digits(length); + m_end = start + length; + } + + namespace + { + // str1 is null-terminated + // str2 is not, str2 is len2 chars + bool string_equal(char const* str1, char const* str2, int len2) + { + while (len2 > 0) + { + if (*str1 != *str2) return false; + if (*str1 == 0) return false; + ++str1; + ++str2; + --len2; + } + return *str1 == 0; + } + } + + std::string lazy_entry::dict_find_string_value(char const* name) const + { + lazy_entry const* e = dict_find(name); + if (e == 0 || e->type() != lazy_entry::string_t) return std::string(); + return e->string_value(); + } + + size_type lazy_entry::dict_find_int_value(char const* name, size_type default_val) const + { + lazy_entry const* e = dict_find(name); + if (e == 0 || e->type() != lazy_entry::int_t) return default_val; + return e->int_value(); + } + + lazy_entry const* lazy_entry::dict_find_dict(char const* name) const + { + lazy_entry const* e = dict_find(name); + if (e == 0 || e->type() != lazy_entry::dict_t) return 0; + return e; + } + + lazy_entry const* lazy_entry::dict_find_list(char const* name) const + { + lazy_entry const* e = dict_find(name); + if (e == 0 || e->type() != lazy_entry::list_t) return 0; + return e; + } + + lazy_entry* lazy_entry::dict_find(char const* name) + { + TORRENT_ASSERT(m_type == dict_t); + for (int i = 0; i < m_size; ++i) + { + std::pair const& e = m_data.dict[i]; + if (string_equal(name, e.first, e.second.m_begin - e.first)) + return &m_data.dict[i].second; + } + return 0; + } + + lazy_entry* lazy_entry::list_append() + { + TORRENT_ASSERT(m_type == list_t); + TORRENT_ASSERT(m_size <= m_capacity); + if (m_capacity == 0) + { + int capacity = lazy_entry_list_init; + m_data.list = new (std::nothrow) lazy_entry[capacity]; + if (m_data.list == 0) return 0; + m_capacity = capacity; + } + else if (m_size == m_capacity) + { + int capacity = m_capacity * lazy_entry_grow_factor; + lazy_entry* tmp = new (std::nothrow) lazy_entry[capacity]; + if (tmp == 0) return 0; + std::memcpy(tmp, m_data.list, sizeof(lazy_entry) * m_size); + for (int i = 0; i < m_size; ++i) m_data.list[i].release(); + delete[] m_data.list; + m_data.list = tmp; + m_capacity = capacity; + } + + TORRENT_ASSERT(m_size < m_capacity); + return m_data.list + (m_size++); + } + + std::string lazy_entry::list_string_value_at(int i) const + { + lazy_entry const* e = list_at(i); + if (e == 0 || e->type() != lazy_entry::string_t) return std::string(); + return e->string_value(); + } + + size_type lazy_entry::list_int_value_at(int i, size_type default_val) const + { + lazy_entry const* e = list_at(i); + if (e == 0 || e->type() != lazy_entry::int_t) return default_val; + return e->int_value(); + } + + void lazy_entry::clear() + { + switch (m_type) + { + case list_t: delete[] m_data.list; break; + case dict_t: delete[] m_data.dict; break; + default: break; + } + m_data.start = 0; + m_size = 0; + m_capacity = 0; + m_type = none_t; + } + + std::pair lazy_entry::data_section() const + { + typedef std::pair return_t; + return return_t(m_begin, m_end - m_begin); + } + + std::ostream& operator<<(std::ostream& os, lazy_entry const& e) + { + switch (e.type()) + { + case lazy_entry::none_t: return os << "none"; + case lazy_entry::int_t: return os << e.int_value(); + case lazy_entry::string_t: + { + bool printable = true; + char const* str = e.string_ptr(); + for (int i = 0; i < e.string_length(); ++i) + { + using namespace std; + if (isprint(str[i])) continue; + printable = false; + break; + } + os << "'"; + if (printable) return os << e.string_value() << "'"; + for (int i = 0; i < e.string_length(); ++i) + os << std::hex << int((unsigned char)(str[i])); + return os << "'"; + } + case lazy_entry::list_t: + { + os << "["; + bool one_liner = (e.list_size() == 0 + || e.list_at(0)->type() == lazy_entry::int_t + || (e.list_at(0)->type() == lazy_entry::string_t + && (e.list_at(0)->string_length() < 10 + || e.list_size() < 2))) + && e.list_size() < 5; + if (!one_liner) os << "\n"; + for (int i = 0; i < e.list_size(); ++i) + { + if (i == 0 && one_liner) os << " "; + os << *e.list_at(i); + if (i < e.list_size() - 1) os << (one_liner?", ":",\n"); + else os << (one_liner?" ":"\n"); + } + return os << "]"; + } + case lazy_entry::dict_t: + { + os << "{"; + bool one_liner = (e.dict_size() == 0 + || e.dict_at(0).second->type() == lazy_entry::int_t + || (e.dict_at(0).second->type() == lazy_entry::string_t + && e.dict_at(0).second->string_length() < 30) + || e.dict_at(0).first.size() < 10) + && e.dict_size() < 5; + + if (!one_liner) os << "\n"; + for (int i = 0; i < e.dict_size(); ++i) + { + if (i == 0 && one_liner) os << " "; + std::pair ent = e.dict_at(i); + os << "'" << ent.first << "': " << *ent.second; + if (i < e.dict_size() - 1) os << (one_liner?", ":",\n"); + else os << (one_liner?" ":"\n"); + } + return os << "}"; + } + } + return os; + } + +}; + diff --git a/libtorrent/src/logger.cpp b/libtorrent/src/logger.cpp index b33816a59..1ecba5045 100644 --- a/libtorrent/src/logger.cpp +++ b/libtorrent/src/logger.cpp @@ -81,11 +81,10 @@ namespace virtual void add_handshake(entry&) {} // called when the extension handshake from the other end is received - virtual bool on_extension_handshake(entry const& h) + virtual bool on_extension_handshake(lazy_entry const& h) { log_timestamp(); - m_file << "<== EXTENSION_HANDSHAKE\n"; - h.print(m_file); + m_file << "<== EXTENSION_HANDSHAKE\n" << h; return true; } diff --git a/libtorrent/src/lsd.cpp b/libtorrent/src/lsd.cpp index 8ec1a5daf..2d4e8b7da 100644 --- a/libtorrent/src/lsd.cpp +++ b/libtorrent/src/lsd.cpp @@ -35,11 +35,18 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/lsd.hpp" #include "libtorrent/io.hpp" #include "libtorrent/http_tracker_connection.hpp" +#include "libtorrent/buffer.hpp" +#include "libtorrent/http_parser.hpp" #include #include +#if BOOST_VERSION < 103500 #include #include +#else +#include +#include +#endif #include #include #include @@ -50,7 +57,7 @@ using namespace libtorrent; namespace libtorrent { // defined in broadcast_socket.cpp - address guess_local_address(asio::io_service&); + address guess_local_address(io_service&); } lsd::lsd(io_service& ios, address const& listen_interface @@ -82,7 +89,7 @@ void lsd::announce(sha1_hash const& ih, int listen_port) std::string const& msg = btsearch.str(); m_retry_count = 1; - asio::error_code ec; + error_code ec; m_socket.send(msg.c_str(), int(msg.size()), ec); if (ec) { @@ -95,26 +102,24 @@ void lsd::announce(sha1_hash const& ih, int listen_port) << " ==> announce: ih: " << ih << " port: " << listen_port << std::endl; #endif - m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count)); + m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec); m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg)); } -void lsd::resend_announce(asio::error_code const& e, std::string msg) try +void lsd::resend_announce(error_code const& e, std::string msg) { if (e) return; - asio::error_code ec; + error_code ec; m_socket.send(msg.c_str(), int(msg.size()), ec); ++m_retry_count; if (m_retry_count >= 5) return; - m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count)); + m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec); m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg)); } -catch (std::exception&) -{} void lsd::on_announce(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred) @@ -123,9 +128,11 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer http_parser p; - p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred)); + bool error = false; + p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred) + , error); - if (!p.header_finished()) + if (!p.header_finished() || error) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log << time_now_string() @@ -176,15 +183,22 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer << ":" << port << " ih: " << ih << std::endl; #endif // we got an announce, pass it on through the callback - try { m_callback(tcp::endpoint(from.address(), port), ih); } +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + m_callback(tcp::endpoint(from.address(), port), ih); +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception&) {} +#endif } } void lsd::close() { m_socket.close(); - m_broadcast_timer.cancel(); + error_code ec; + m_broadcast_timer.cancel(ec); m_disabled = true; m_callback.clear(); } diff --git a/libtorrent/src/magnet_uri.cpp b/libtorrent/src/magnet_uri.cpp new file mode 100644 index 000000000..bd582476a --- /dev/null +++ b/libtorrent/src/magnet_uri.cpp @@ -0,0 +1,100 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +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. + +*/ + +#include "libtorrent/magnet_uri.hpp" +#include "libtorrent/session.hpp" +#include "libtorrent/torrent_handle.hpp" +#include "libtorrent/escape_string.hpp" + +#include +#include + +namespace libtorrent +{ + std::string make_magnet_uri(torrent_handle const& handle) + { + std::stringstream ret; + if (!handle.is_valid()) return ret.str(); + + std::string name = handle.name(); + + ret << "magnet:?xt=urn:btih:" << base32encode( + std::string((char*)handle.info_hash().begin(), 20)); + if (!name.empty()) + ret << "&dn=" << escape_string(name.c_str(), name.length()); + torrent_status st = handle.status(); + if (!st.current_tracker.empty()) + { + ret << "&tr=" << escape_string(st.current_tracker.c_str() + , st.current_tracker.length()); + } + else + { + std::vector const& tr = handle.trackers(); + if (!tr.empty()) + { + ret << "&tr=" << escape_string(tr[0].url.c_str() + , tr[0].url.length()); + } + } + return ret.str(); + } + + torrent_handle add_magnet_uri(session& ses, std::string const& uri + , fs::path const& save_path + , storage_mode_t storage_mode + , bool paused + , storage_constructor_type sc + , void* userdata) + { + std::string name; + std::string tracker; + + boost::optional display_name = url_has_argument(uri, "dn"); + if (display_name) name = unescape_string(display_name->c_str()); + boost::optional tracker_string = url_has_argument(uri, "tr"); + if (tracker_string) tracker = unescape_string(tracker_string->c_str()); + + boost::optional btih = url_has_argument(uri, "xt"); + if (!btih) return torrent_handle(); + + if (btih->compare(0, 9, "urn:btih:") != 0) return torrent_handle(); + + sha1_hash info_hash(base32decode(btih->substr(9))); + + return ses.add_torrent(tracker.empty() ? 0 : tracker.c_str(), info_hash + , name.empty() ? 0 : name.c_str(), save_path, entry() + , storage_mode, paused, sc, userdata); + } +} + + diff --git a/libtorrent/src/mapped_storage.cpp b/libtorrent/src/mapped_storage.cpp new file mode 100644 index 000000000..e5cf4647a --- /dev/null +++ b/libtorrent/src/mapped_storage.cpp @@ -0,0 +1,864 @@ +/* + +Copyright (c) 2007, Arvid Norberg, Daniel Wallin +All rights reserved. + +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. + +*/ + +#include "libtorrent/pch.hpp" + +#include "libtorrent/storage.hpp" +#include "libtorrent/size_type.hpp" +#include "libtorrent/file.hpp" +#include + +#ifdef _MSC_VER +#pragma warning(push, 1) +#endif + +#include +#include +#include +#include +#include +#include +#if BOOST_VERSION >= 103500 +#include +#endif + +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +using boost::iostreams::mapped_file; +using boost::iostreams::mapped_file_params; + +namespace libtorrent +{ + namespace fs = boost::filesystem; +#if BOOST_VERSION >= 103500 + typedef boost::system::error_code ec_t; +#else + typedef error_code ec_t; +#endif + + struct mapped_file_pool + { + mapped_file_pool(int size = 40): m_size(size) {} + + private: + + enum { view_size = 100 * 1024 * 1024 }; + int m_size; + + struct file_entry + { + file_entry() : key(0), references(0) {} + bool open(fs::path const& path, std::ios::openmode openmode + , size_type start, size_type size, void* key_, size_type file_size = 0) + { +#ifndef NDEBUG + if (file_size > 0) + { + ec_t ec; + fs::file_status st = fs::status(path, ec); + TORRENT_ASSERT(!fs::exists(st)); + } +#endif + key = key_; + last_use = time_now(); + params.path = path.string(); + params.mode = openmode; + params.offset = start; + params.length = size; + params.new_file_size = file_size; + file.open(params); + return file.is_open(); + } + mapped_file_params params; + mapped_file file; + void* key; + ptime last_use; + int references; + }; + + typedef std::list files_t; + files_t m_files; + + public: + + struct file_view + { + explicit file_view(file_entry* e): m_entry(e) { ++m_entry->references; } + file_view(): m_entry(0) {} + file_view(file_view const& f): m_entry(f.m_entry) + { if (m_entry) ++m_entry->references; } + ~file_view() + { + TORRENT_ASSERT(m_entry == 0 || m_entry->references > 0); + if (m_entry) --m_entry->references; + } + file_view& operator=(file_view const& v) + { + TORRENT_ASSERT(m_entry == 0 || m_entry->references > 0); + if (m_entry) --m_entry->references; + m_entry = v.m_entry; + if (m_entry) ++m_entry->references; + return *this; + } + + bool valid() const { return m_entry && m_entry->file.const_data(); } + + char* addr() const + { + TORRENT_ASSERT(m_entry); + return m_entry->file.data(); + } + + char const* const_addr() const + { + TORRENT_ASSERT(m_entry); + return m_entry->file.const_data(); + } + + size_type offset() const + { + TORRENT_ASSERT(m_entry); + return m_entry->params.offset; + } + + size_type size() const + { + TORRENT_ASSERT(m_entry); + return m_entry->params.length; + } + + private: + file_entry* m_entry; + }; + + file_view open_file(fs::path const& p, std::ios::openmode mode + , size_type offset, size_type length, void* key + , size_type file_size) + { + TORRENT_ASSERT(file_size > 0); + files_t::iterator min = m_files.end(); + for (std::list::iterator i = m_files.begin() + , end(m_files.end()); i != end; ++i) + { + if (i->params.path == p.string() + && i->params.offset <= offset + && i->params.offset + i->params.length >= offset + length) + { + if (i->key != key) return file_view(); + if ((mode & std::ios::out) && (i->params.mode & std::ios::out) == 0) + { + TORRENT_ASSERT(i->references == 0); + i->file.close(); + m_files.erase(i); + min = m_files.end(); + break; + } + i->last_use = time_now(); + return file_view(&(*i)); + } + if ((min == m_files.end() || i->last_use < min->last_use) + && i->references == 0) + { + min = i; + } + } + + if (int(m_files.size()) >= m_size && min != m_files.end()) + { + TORRENT_ASSERT(min->references == 0); + min->file.close(); + m_files.erase(min); + } + + size_type start = (offset / view_size) * view_size; + TORRENT_ASSERT(start + view_size >= offset + length); + +#if BOOST_VERSION < 103500 + fs::system_error_type ec; +#else + ec_t ec; +#endif + fs::file_status st = fs::status(p, ec); + + m_files.push_back(file_entry()); + bool ret = false; + if (!exists(st)) + { + ret = m_files.back().open(p, mode | std::ios::out, start, view_size, key, file_size); + } + else + { + if (is_directory(st)) return file_view(); + size_type s = fs::file_size(p); +#ifdef WIN32 + // TODO: SetFileSize() + if (s < file_size) {} +#else + if (s < file_size) truncate(p.string().c_str(), file_size); +#endif + ret = m_files.back().open(p, mode, start, view_size, key); + } + + + if (!ret) + { + m_files.erase(boost::prior(m_files.end())); + return file_view(); + } + return file_view(&m_files.back()); + } + + void release(void* key) + { + for (std::list::iterator i = m_files.begin(); + !m_files.empty() && i != m_files.end();) + { + if (i->key == key) + { + TORRENT_ASSERT(i->references == 0); + i->file.close(); + m_files.erase(i++); + continue; + } + ++i; + } + } + + }; + + + struct mapped_storage: storage_interface + { + mapped_storage(file_storage const& fs, fs::path save_path) + : m_files(fs) + , m_save_path(save_path) + {} + + bool initialize(bool allocate_files) { return false; } + + int read(char* buf, int slot, int offset, int size) + { + TORRENT_ASSERT(buf != 0); + TORRENT_ASSERT(slot >= 0 && slot < m_files.num_pieces()); + TORRENT_ASSERT(offset >= 0); + TORRENT_ASSERT(offset < m_files.piece_size(slot)); + TORRENT_ASSERT(size > 0); + + size_type result = -1; + try + { + +#ifndef NDEBUG + std::vector slices + = files().map_block(slot, offset, size); + TORRENT_ASSERT(!slices.empty()); +#endif + size_type start = slot * (size_type)m_files.piece_length() + offset; + TORRENT_ASSERT(start + size <= m_files.total_size()); + + // find the file iterator and file offset + size_type file_offset = start; + std::vector::const_iterator file_iter; + + for (file_iter = files().begin();;) + { + if (file_offset < file_iter->size) + break; + + file_offset -= file_iter->size; + ++file_iter; + } + + TORRENT_ASSERT(file_iter->size > 0); + mapped_file_pool::file_view view = m_pool.open_file( + m_save_path / file_iter->path, std::ios::in + , file_offset + file_iter->file_base, size, this + , file_iter->size + file_iter->file_base); + + if (!view.valid()) + { + set_error((m_save_path / file_iter->path).string(), "failed to open file for reading"); + return -1; + } + TORRENT_ASSERT(view.const_addr() != 0); + + int left_to_read = size; + int buf_pos = 0; + result = left_to_read; +#ifndef NDEBUG + int counter = 0; +#endif + while (left_to_read > 0) + { + int read_bytes = left_to_read; + if (file_offset + read_bytes > file_iter->size) + read_bytes = static_cast(file_iter->size - file_offset); + + if (read_bytes > 0) + { +#ifndef NDEBUG + TORRENT_ASSERT(int(slices.size()) > counter); + size_type slice_size = slices[counter].size; + TORRENT_ASSERT(slice_size == read_bytes); + TORRENT_ASSERT(files().at(slices[counter].file_index).path + == file_iter->path); +#endif + + TORRENT_ASSERT(file_offset + file_iter->file_base >= view.offset()); + TORRENT_ASSERT(view.const_addr() != 0); + std::memcpy(buf + buf_pos + , view.const_addr() + (file_offset + file_iter->file_base - view.offset()) + , read_bytes); + + left_to_read -= read_bytes; + buf_pos += read_bytes; + TORRENT_ASSERT(buf_pos >= 0); + file_offset += read_bytes; + } + + if (left_to_read > 0) + { + ++file_iter; + // skip empty files + while (file_iter != files().end() && file_iter->size == 0) + ++file_iter; + +#ifndef NDEBUG + // empty files are not returned by map_block, so if + // this file was empty, don't increment the slice counter + if (read_bytes > 0) ++counter; +#endif + fs::path path = m_save_path / file_iter->path; + + file_offset = 0; + + view = m_pool.open_file(path, std::ios::in, file_offset + file_iter->file_base + , left_to_read, this + , file_iter->size + file_iter->file_base); + + if (!view.valid()) + { + set_error((m_save_path / file_iter->path).string(), "failed to open for reading"); + return -1; + } + TORRENT_ASSERT(view.const_addr() != 0); + } + } + } + catch (std::exception& e) + { + set_error("", e.what()); + return -1; + } + + return result; + } + + int write(const char* buf, int slot, int offset, int size) + { + TORRENT_ASSERT(buf != 0); + TORRENT_ASSERT(slot >= 0 && slot < m_files.num_pieces()); + TORRENT_ASSERT(offset >= 0); + TORRENT_ASSERT(offset < m_files.piece_size(slot)); + TORRENT_ASSERT(size > 0); + +#ifndef NDEBUG + std::vector slices + = files().map_block(slot, offset, size); + TORRENT_ASSERT(!slices.empty()); +#endif + size_type start = slot * (size_type)m_files.piece_length() + offset; + TORRENT_ASSERT(start + size <= m_files.total_size()); + + // find the file iterator and file offset + size_type file_offset = start; + std::vector::const_iterator file_iter; + + for (file_iter = files().begin();;) + { + if (file_offset < file_iter->size) + break; + + file_offset -= file_iter->size; + ++file_iter; + } + + TORRENT_ASSERT(file_iter->size > 0); + try + { + + mapped_file_pool::file_view view = m_pool.open_file( + m_save_path / file_iter->path, std::ios::in | std::ios::out + , file_offset + file_iter->file_base, size, this + , file_iter->size + file_iter->file_base); + + if (!view.valid()) + { + set_error((m_save_path / file_iter->path).string(), "failed to open file for writing"); + return -1; + } + TORRENT_ASSERT(view.addr() != 0); + + int left_to_write = size; + int buf_pos = 0; +#ifndef NDEBUG + int counter = 0; +#endif + while (left_to_write > 0) + { + int write_bytes = left_to_write; + if (file_offset + write_bytes > file_iter->size) + write_bytes = static_cast(file_iter->size - file_offset); + + if (write_bytes > 0) + { +#ifndef NDEBUG + TORRENT_ASSERT(int(slices.size()) > counter); + size_type slice_size = slices[counter].size; + TORRENT_ASSERT(slice_size == write_bytes); + TORRENT_ASSERT(files().at(slices[counter].file_index).path + == file_iter->path); +#endif + + TORRENT_ASSERT(file_offset + file_iter->file_base >= view.offset()); + TORRENT_ASSERT(view.addr() != 0); + std::memcpy(view.addr() + (file_offset + file_iter->file_base - view.offset()) + , buf + buf_pos + , write_bytes); + + left_to_write -= write_bytes; + buf_pos += write_bytes; + TORRENT_ASSERT(buf_pos >= 0); + file_offset += write_bytes; + } + + if (left_to_write > 0) + { + ++file_iter; + while (file_iter != files().end() && file_iter->size == 0) + ++file_iter; +#ifndef NDEBUG + // empty files are not returned by map_block, so if + // this file was empty, don't increment the slice counter + if (write_bytes > 0) ++counter; +#endif + fs::path path = m_save_path / file_iter->path; + + file_offset = 0; + view = m_pool.open_file(path, std::ios::in | std::ios::out + , file_offset + file_iter->file_base, left_to_write, this + , file_iter->size + file_iter->file_base); + + if (!view.valid()) + { + set_error((m_save_path / file_iter->path).string(), "failed to open file for reading"); + return -1; + } + TORRENT_ASSERT(view.addr() != 0); + } + } + } + catch (std::exception& e) + { + set_error((m_save_path / file_iter->path).string(), e.what()); + return -1; + } + return size; + } + + bool move_storage(fs::path save_path) + { +#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400 + fs::wpath old_path; + fs::wpath new_path; +#else + fs::path old_path; + fs::path new_path; +#endif + + save_path = complete(save_path); + +#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 + std::wstring wsave_path(safe_convert(save_path.native_file_string())); + if (!exists_win(save_path)) + CreateDirectory(wsave_path.c_str(), 0); + else if ((GetFileAttributes(wsave_path.c_str()) & FILE_ATTRIBUTE_DIRECTORY) == 0) + return false; +#elif defined(_WIN32) && defined(UNICODE) + fs::wpath wp = safe_convert(save_path.string()); + if (!exists(wp)) + create_directory(wp); + else if (!is_directory(wp)) + return false; +#else + if (!exists(save_path)) + create_directory(save_path); + else if (!is_directory(save_path)) + return false; +#endif + + m_pool.release(this); + +#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400 + old_path = safe_convert((m_save_path / files().name()).string()); + new_path = safe_convert((save_path / files().name()).string()); +#else + old_path = m_save_path / files().name(); + new_path = save_path / files().name(); +#endif + + try + { +#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 + rename_win(old_path, new_path); + rename(old_path, new_path); +#else + rename(old_path, new_path); +#endif + m_save_path = save_path; + return true; + } + catch (std::exception& e) + { +#ifndef NDEBUG + std::cerr << "ERROR: " << e.what() << std::endl; +#endif + } + return false; + } + + bool verify_resume_data(lazy_entry const& rd, std::string& error) + { + if (rd.type() != lazy_entry::dict_t) + { + error = "invalid fastresume file (not a dictionary)"; + return true; + } + + std::vector > file_sizes; + lazy_entry const* file_sizes_ent = rd.dict_find_list("file sizes"); + if (file_sizes_ent == 0) + { + error = "missing or invalid 'file sizes' entry in resume data"; + return false; + } + + for (int i = 0; i < file_sizes_ent->list_size(); ++i) + { + lazy_entry const* e = file_sizes_ent->list_at(i); + if (e->type() != lazy_entry::list_t + || e->list_size() != 2 + || e->list_at(0)->type() != lazy_entry::int_t + || e->list_at(1)->type() != lazy_entry::int_t) + continue; + file_sizes.push_back(std::pair( + e->list_int_value_at(0), std::time_t(e->list_int_value_at(1)))); + } + + if (file_sizes.empty()) + { + error = "the number of files in resume data is 0"; + return false; + } + + lazy_entry const* slots = rd.dict_find_list("slots"); + if (slots == 0) + { + error = "missing or invalid 'slots' entry in resume data"; + return false; + } + + bool seed = false; + + if (int(slots->list_size()) == m_files.num_pieces()) + { + bool seed = true; + for (int i = 0; i < slots->list_size(); ++i) + { + lazy_entry const* e = slots->list_at(i); + if (e->list_int_value_at(i, -1) >= 0) continue; + seed = false; + break; + } + } + + bool full_allocation_mode = false; + if (rd.dict_find_string_value("allocation") == "full") + full_allocation_mode = true; + + if (seed) + { + if (files().num_files() != (int)file_sizes.size()) + { + error = "the number of files does not match the torrent (num: " + + boost::lexical_cast(file_sizes.size()) + " actual: " + + boost::lexical_cast(files().num_files()) + ")"; + return false; + } + + std::vector >::iterator + fs = file_sizes.begin(); + // the resume data says we have the entire torrent + // make sure the file sizes are the right ones + for (file_storage::iterator i = files().begin() + , end(files().end()); i != end; ++i, ++fs) + { + if (i->size != fs->first) + { + error = "file size for '" + i->path.native_file_string() + + "' was expected to be " + + boost::lexical_cast(i->size) + " bytes"; + return false; + } + } + } + + return match_filesizes(files(), m_save_path, file_sizes + , !full_allocation_mode, &error); + } + + bool write_resume_data(entry& rd) const + { + if (rd.type() != entry::dictionary_t) + { + set_error("", "invalid fastresume file"); + return true; + } + std::vector > file_sizes + = get_filesizes(m_files, m_save_path); + + entry::list_type& fl = rd["file sizes"].list(); + for (std::vector >::iterator i + = file_sizes.begin(), end(file_sizes.end()); i != end; ++i) + { + entry::list_type p; + p.push_back(entry(i->first)); + p.push_back(entry(i->second)); + fl.push_back(entry(p)); + } + return false; + } + + bool move_slot(int src_slot, int dst_slot) + { + // TODO: this can be optimized by mapping both slots and do a straight memcpy + int piece_size = m_files.piece_size(dst_slot); + m_scratch_buffer.resize(piece_size); + size_type ret1 = read(&m_scratch_buffer[0], src_slot, 0, piece_size); + size_type ret2 = write(&m_scratch_buffer[0], dst_slot, 0, piece_size); + return ret1 != piece_size || ret2 != piece_size; + } + + bool swap_slots(int slot1, int slot2) + { + // TODO: this can be optimized by mapping both slots and do a straight memcpy + // the size of the target slot is the size of the piece + int piece_size = m_files.piece_length(); + int piece1_size = m_files.piece_size(slot2); + int piece2_size = m_files.piece_size(slot1); + m_scratch_buffer.resize(piece_size * 2); + size_type ret1 = read(&m_scratch_buffer[0], slot1, 0, piece1_size); + size_type ret2 = read(&m_scratch_buffer[piece_size], slot2, 0, piece2_size); + size_type ret3 = write(&m_scratch_buffer[0], slot2, 0, piece1_size); + size_type ret4 = write(&m_scratch_buffer[piece_size], slot1, 0, piece2_size); + return ret1 != piece1_size || ret2 != piece2_size + || ret3 != piece1_size || ret4 != piece2_size; + } + + bool swap_slots3(int slot1, int slot2, int slot3) + { + // TODO: this can be optimized by mapping both slots and do a straight memcpy + // the size of the target slot is the size of the piece + int piece_size = m_files.piece_length(); + int piece1_size = m_files.piece_size(slot2); + int piece2_size = m_files.piece_size(slot3); + int piece3_size = m_files.piece_size(slot1); + m_scratch_buffer.resize(piece_size * 2); + size_type ret1 = read(&m_scratch_buffer[0], slot1, 0, piece1_size); + size_type ret2 = read(&m_scratch_buffer[piece_size], slot2, 0, piece2_size); + size_type ret3 = write(&m_scratch_buffer[0], slot2, 0, piece1_size); + size_type ret4 = read(&m_scratch_buffer[0], slot3, 0, piece3_size); + size_type ret5 = write(&m_scratch_buffer[piece_size], slot3, 0, piece2_size); + size_type ret6 = write(&m_scratch_buffer[0], slot1, 0, piece3_size); + return ret1 != piece1_size || ret2 != piece2_size + || ret3 != piece1_size || ret4 != piece3_size + || ret5 != piece2_size || ret6 != piece3_size; + } + + sha1_hash hash_for_slot(int slot, partial_hash& ph, int piece_size) + { +#ifndef NDEBUG + hasher partial; + hasher whole; + int slot_size1 = piece_size; + m_scratch_buffer.resize(slot_size1); + read(&m_scratch_buffer[0], slot, 0, slot_size1); + if (ph.offset > 0) + partial.update(&m_scratch_buffer[0], ph.offset); + whole.update(&m_scratch_buffer[0], slot_size1); + hasher partial_copy = ph.h; + TORRENT_ASSERT(ph.offset == 0 || partial_copy.final() == partial.final()); +#endif + int slot_size = piece_size - ph.offset; + if (slot_size > 0) + { + m_scratch_buffer.resize(slot_size); + read(&m_scratch_buffer[0], slot, ph.offset, slot_size); + ph.h.update(&m_scratch_buffer[0], slot_size); + } +#ifndef NDEBUG + sha1_hash ret = ph.h.final(); + TORRENT_ASSERT(ret == whole.final()); + return ret; +#else + return ph.h.final(); +#endif + } + + bool rename_file(int index, std::string const& new_filename) + { + if (index < 0 || index >= m_files.num_files()) return true; + fs::path old_name = m_save_path / files().at(index).path; + m_pool.release(this); + +#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400 + fs::wpath old_path = safe_convert(old_name.string()); + fs::wpath new_path = safe_convert((m_save_path / new_filename).string()); +#else + fs::path const& old_path = old_name; + fs::path new_path = m_save_path / new_filename; +#endif + +#ifndef BOOST_NO_EXCEPTIONS + try + { +#endif + rename(old_path, new_path); + if (!m_mapped_files) + { m_mapped_files.reset(new file_storage(m_files)); } + m_mapped_files->rename_file(index, new_filename); +#ifndef BOOST_NO_EXCEPTIONS + } + catch (std::exception& e) + { + set_error(old_name.string(), e.what()); + return true; + } +#endif + return false; + } + + bool release_files() + { + m_pool.release(this); + return false; + } + + bool delete_files() + { + // make sure we don't have the files open + m_pool.release(this); + buffer().swap(m_scratch_buffer); + + int result = 0; + std::string error; + std::string error_file; + + // delete the files from disk + std::set directories; + typedef std::set::iterator iter_t; + for (file_storage::iterator i = m_files.begin() + , end(m_files.end()); i != end; ++i) + { + std::string p = (m_save_path / i->path).string(); + fs::path bp = i->path.branch_path(); + std::pair ret; + ret.second = true; + while (ret.second && !bp.empty()) + { + std::pair ret = directories.insert((m_save_path / bp).string()); + bp = bp.branch_path(); + } + if (std::remove(p.c_str()) != 0 && errno != ENOENT) + { + error = std::strerror(errno); + error_file = p; + result = errno; + } + } + + // remove the directories. Reverse order to delete + // subdirectories first + + for (std::set::reverse_iterator i = directories.rbegin() + , end(directories.rend()); i != end; ++i) + { + if (std::remove(i->c_str()) != 0 && errno != ENOENT) + { + error = std::strerror(errno); + error_file = *i; + result = errno; + } + } + + if (!error.empty()) set_error(error_file, error); + return result != 0; + } + + private: + + file_storage const& files() const { return m_mapped_files?*m_mapped_files:m_files; } + + boost::scoped_ptr m_mapped_files; + file_storage const& m_files; + fs::path m_save_path; + + // temporary storage for moving pieces + buffer m_scratch_buffer; + + static mapped_file_pool m_pool; + }; + + storage_interface* mapped_storage_constructor(file_storage const& fs + , fs::path const& path, file_pool& fp) + { + return new mapped_storage(fs, path); + } + + mapped_file_pool mapped_storage::m_pool; + +} + diff --git a/libtorrent/src/memdebug.cpp b/libtorrent/src/memdebug.cpp new file mode 100644 index 000000000..bdc5aa3f2 --- /dev/null +++ b/libtorrent/src/memdebug.cpp @@ -0,0 +1,224 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +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. + +*/ + +#if defined __linux__ && defined __GNUC__ +#include + +// Prototypes for __malloc_hook, __free_hook +#include +#include +#include +#include +#include +#include +#include +#include +#include "libtorrent/time.hpp" +#include "libtorrent/assert.hpp" + +using boost::multi_index_container; +using namespace boost::multi_index; +using libtorrent::time_now; + +struct memdebug +{ + memdebug() + { + malloc_log.open("memory.log"); + malloc_index_log.open("memory_index.log"); + + assert(old_malloc_hook == 0); + assert(old_free_hook == 0); + old_malloc_hook = __malloc_hook; + old_free_hook = __free_hook; + __malloc_hook = my_malloc_hook; + __free_hook = my_free_hook; + } + + static void my_free_hook(void *ptr, const void *caller); + static void* my_malloc_hook(size_t size, const void *caller); + + static boost::mutex mutex; + static std::ofstream malloc_log; + static std::ofstream malloc_index_log; + + // the original library functions + static void* (*old_malloc_hook)(size_t, const void *); + static void (*old_free_hook)(void*, const void *); + + struct allocation_point_t + { + allocation_point_t() + : allocated(0) + , peak_allocated(0) + , spacetime(0) + , last_update(time_now()) {} + + int index; + // total number of bytes allocated from this point + int allocated; + // the maximum total number of bytes allocated + // from this point + int peak_allocated; + // total number of bytes allocated times the number of + // milliseconds they were allocated from this point + boost::int64_t spacetime; + // the last malloc or free operation on + // this allocation point. The spacetime + // should be updated from this point to + // the current operation + libtorrent::ptime last_update; + }; + + typedef boost::array stacktrace_t; + typedef std::map allocation_map_t; + static allocation_map_t allocation_points; + static std::map > allocations; + static int allocation_point_index; + static libtorrent::ptime start_time; +}; + +boost::mutex memdebug::mutex; +int memdebug::allocation_point_index = 0; +std::ofstream memdebug::malloc_log; +std::ofstream memdebug::malloc_index_log; +void* (*memdebug::old_malloc_hook)(size_t, const void *) = 0; +void (*memdebug::old_free_hook)(void*, const void *) = 0; +memdebug::allocation_map_t memdebug::allocation_points; +std::map > memdebug::allocations; +libtorrent::ptime memdebug::start_time = time_now(); + +void* memdebug::my_malloc_hook(size_t size, const void *caller) +{ + boost::mutex::scoped_lock l(mutex); + /* Restore all old hooks */ + __malloc_hook = old_malloc_hook; + __free_hook = old_free_hook; + /* Call recursively */ + void* result = malloc(size); + /* Save underlying hooks */ + old_malloc_hook = __malloc_hook; + old_free_hook = __free_hook; + + stacktrace_t stack; + int stacksize = backtrace(&stack[0], stack.size()); + libtorrent::ptime now = time_now(); + + allocation_map_t::iterator i = allocation_points.lower_bound(stack); + if (i == allocation_points.end() || i->first != stack) + { + i = allocation_points.insert(i, std::make_pair(stack, allocation_point_t())); + i->second.index = allocation_point_index++; + i->second.allocated = size; + + malloc_index_log << i->second.index << "#"; + char** symbols = backtrace_symbols(&stack[0], stacksize); + for (int j = 2; j < stacksize; ++j) + malloc_index_log << demangle(symbols[j]) << "#"; + malloc_index_log << std::endl; + } + else + { + allocation_point_t& ap = i->second; + ap.spacetime += libtorrent::total_milliseconds(now - ap.last_update) * ap.allocated; + ap.allocated += size; + if (ap.allocated > ap.peak_allocated) ap.peak_allocated = ap.allocated; + ap.last_update = now; + } + allocation_point_t& ap = i->second; + + allocations[result] = std::make_pair(i, size); + malloc_log << "#" << ap.index << " " + << libtorrent::total_milliseconds(time_now() - start_time) << " A " + << result << " " << size << " " << ap.allocated << " " << ap.spacetime + << " " << ap.peak_allocated << std::endl; + + /* Restore our own hooks */ + __malloc_hook = my_malloc_hook; + __free_hook = my_free_hook; + return result; +} + +void memdebug::my_free_hook(void *ptr, const void *caller) +{ + boost::mutex::scoped_lock l(mutex); + /* Restore all old hooks */ + __malloc_hook = old_malloc_hook; + __free_hook = old_free_hook; + /* Call recursively */ + free(ptr); + /* Save underlying hooks */ + old_malloc_hook = __malloc_hook; + old_free_hook = __free_hook; + + std::map >::iterator i + = allocations.find(ptr); + + if (i != allocations.end()) + { + allocation_point_t& ap = i->second.first->second; + int size = i->second.second; + ap.allocated -= size; + malloc_log << "#" << ap.index << " " + << libtorrent::total_milliseconds(time_now() - start_time) << " F " + << ptr << " " << size << " " << ap.allocated << " " << ap.spacetime + << " " << ap.peak_allocated << std::endl; + + allocations.erase(i); + } + + /* Restore our own hooks */ + __malloc_hook = my_malloc_hook; + __free_hook = my_free_hook; +} + +static int ref_count = 0; + +void start_malloc_debug() +{ + boost::mutex::scoped_lock l(memdebug::mutex); + static memdebug mi; + ++ref_count; +} + +void stop_malloc_debug() +{ + boost::mutex::scoped_lock l(memdebug::mutex); + if (--ref_count == 0) + { + __malloc_hook = memdebug::old_malloc_hook; + __free_hook = memdebug::old_free_hook; + } +} + +#endif + diff --git a/libtorrent/src/metadata_transfer.cpp b/libtorrent/src/metadata_transfer.cpp index 0d1aea195..a347223e3 100644 --- a/libtorrent/src/metadata_transfer.cpp +++ b/libtorrent/src/metadata_transfer.cpp @@ -55,6 +55,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/extensions.hpp" #include "libtorrent/extensions/metadata_transfer.hpp" #include "libtorrent/alert_types.hpp" +#include "libtorrent/buffer.hpp" namespace libtorrent { namespace { @@ -107,40 +108,37 @@ namespace libtorrent { namespace virtual void on_files_checked() { - // if the torrent is a seed, copy the metadata from - // the torrent before it is deallocated - if (m_torrent.is_seed()) - metadata(); + // if the torrent is a seed, make a reference to + // the metadata from the torrent before it is deallocated + if (m_torrent.is_seed()) metadata(); } virtual boost::shared_ptr new_connection( peer_connection* pc); - std::vector const& metadata() const + buffer::const_interval metadata() const { - if (m_metadata.empty()) + if (!m_metadata) { - bencode(std::back_inserter(m_metadata) - , m_torrent.torrent_file().create_info_metadata()); - - TORRENT_ASSERT(hasher(&m_metadata[0], m_metadata.size()).final() + m_metadata = m_torrent.torrent_file().metadata(); + m_metadata_size = m_torrent.torrent_file().metadata_size(); + TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final() == m_torrent.torrent_file().info_hash()); } - TORRENT_ASSERT(!m_metadata.empty()); - return m_metadata; + return buffer::const_interval(m_metadata.get(), m_metadata.get() + + m_metadata_size); } bool received_metadata(char const* buf, int size, int offset, int total_size) { if (m_torrent.valid_metadata()) return false; - if ((int)m_metadata.size() < total_size) - m_metadata.resize(total_size); - - std::copy( - buf - , buf + size - , &m_metadata[offset]); + if (!m_metadata || m_metadata_size < total_size) + { + m_metadata.reset(new char[total_size]); + m_metadata_size = total_size; + } + std::copy(buf, buf + size, &m_metadata[offset]); if (m_have_metadata.empty()) m_have_metadata.resize(256, false); @@ -163,7 +161,7 @@ namespace libtorrent { namespace if (!have_all) return false; hasher h; - h.update(&m_metadata[0], (int)m_metadata.size()); + h.update(&m_metadata[0], m_metadata_size); sha1_hash info_hash = h.final(); if (info_hash != m_torrent.torrent_file().info_hash()) @@ -175,17 +173,27 @@ namespace libtorrent { namespace m_metadata_progress = 0; m_metadata_size = 0; - if (m_torrent.alerts().should_post(alert::info)) + if (m_torrent.alerts().should_post()) { m_torrent.alerts().post_alert(metadata_failed_alert( - m_torrent.get_handle(), "invalid metadata received from swarm")); + m_torrent.get_handle())); } return false; } - entry metadata = bdecode(m_metadata.begin(), m_metadata.end()); - m_torrent.set_metadata(metadata); + lazy_entry e; + lazy_bdecode(m_metadata.get(), m_metadata.get() + m_metadata_size, e); + std::string error; + if (!m_torrent.set_metadata(e, error)) + { + // this means the metadata is correct, since we + // verified it against the info-hash, but we + // failed to parse it. Pause the torrent + // TODO: Post an alert! + m_torrent.pause(); + return false; + } // clear the storage for the bitfield std::vector().swap(m_have_metadata); @@ -231,10 +239,10 @@ namespace libtorrent { namespace // the metadata file while downloading it from // peers, and while sending it. // it is mutable because it's generated lazily - mutable std::vector m_metadata; + mutable boost::shared_array m_metadata; int m_metadata_progress; - int m_metadata_size; + mutable int m_metadata_size; // this is a bitfield of size 256, each bit represents // a piece of the metadata. It is set to one if we @@ -270,19 +278,17 @@ namespace libtorrent { namespace } // called when the extension handshake from the other end is received - virtual bool on_extension_handshake(entry const& h) + virtual bool on_extension_handshake(lazy_entry const& h) { - entry const& messages = h["m"]; - if (entry const* index = messages.find_key("LT_metadata")) - { - m_message_index = int(index->integer()); - return true; - } - else - { - m_message_index = 0; - return false; - } + m_message_index = 0; + if (h.type() != lazy_entry::dict_t) return false; + lazy_entry const* messages = h.dict_find("m"); + if (!messages || messages->type() != lazy_entry::dict_t) return false; + + int index = messages->dict_find_int_value("LT_metadata", -1); + if (index == -1) return false; + m_message_index = index; + return true; } void write_metadata_request(std::pair req) @@ -327,7 +333,7 @@ namespace libtorrent { namespace if (m_torrent.valid_metadata() && !m_torrent.torrent_file().priv()) { std::pair offset - = req_to_offset(req, (int)m_tp.metadata().size()); + = req_to_offset(req, (int)m_tp.metadata().left()); buffer::interval i = m_pc.allocate_send_buffer(15 + offset.second); @@ -337,11 +343,11 @@ namespace libtorrent { namespace detail::write_uint8(m_message_index, i.begin); // means 'data packet' detail::write_uint8(1, i.begin); - detail::write_uint32((int)m_tp.metadata().size(), i.begin); + detail::write_uint32((int)m_tp.metadata().left(), i.begin); detail::write_uint32(offset.first, i.begin); - std::vector const& metadata = m_tp.metadata(); - std::copy(metadata.begin() + offset.first - , metadata.begin() + offset.first + offset.second, i.begin); + char const* metadata = m_tp.metadata().begin; + std::copy(metadata + offset.first + , metadata + offset.first + offset.second, i.begin); i.begin += offset.second; TORRENT_ASSERT(i.begin == i.end); } @@ -367,7 +373,10 @@ namespace libtorrent { namespace if (m_message_index == 0) return false; if (length > 500 * 1024) - throw protocol_error("LT_metadata message larger than 500 kB"); + { + m_pc.disconnect("LT_metadata message larger than 500 kB"); + return true; + } if (body.left() < 1) return true; int type = detail::read_uint8(body.begin); @@ -383,7 +392,8 @@ namespace libtorrent { namespace if (length != 3) { // invalid metadata request - throw protocol_error("invalid metadata request"); + m_pc.disconnect("invalid metadata request"); + return true; } write_metadata(std::make_pair(start, size)); @@ -398,13 +408,25 @@ namespace libtorrent { namespace int data_size = length - 9; if (total_size > 500 * 1024) - throw protocol_error("metadata size larger than 500 kB"); + { + m_pc.disconnect("metadata size larger than 500 kB"); + return true; + } if (total_size <= 0) - throw protocol_error("invalid metadata size"); + { + m_pc.disconnect("invalid metadata size"); + return true; + } if (offset > total_size || offset < 0) - throw protocol_error("invalid metadata offset"); + { + m_pc.disconnect("invalid metadata offset"); + return true; + } if (offset + data_size > total_size) - throw protocol_error("invalid metadata message"); + { + m_pc.disconnect("invalid metadata message"); + return true; + } m_tp.metadata_progress(total_size , body.left() - m_metadata_progress); @@ -425,8 +447,11 @@ namespace libtorrent { namespace m_waiting_metadata_request = false; break; default: - throw protocol_error("unknown metadata extension message: " - + boost::lexical_cast(type)); + { + std::stringstream msg; + msg << "unknown metadata extension message: " << type; + m_pc.disconnect(msg.str().c_str()); + } } return true; } diff --git a/libtorrent/src/natpmp.cpp b/libtorrent/src/natpmp.cpp index 38319d18f..9fbe3182d 100644 --- a/libtorrent/src/natpmp.cpp +++ b/libtorrent/src/natpmp.cpp @@ -32,8 +32,14 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/pch.hpp" +#include #include + +#if BOOST_VERSION < 103500 #include +#else +#include +#endif #include "libtorrent/natpmp.hpp" #include "libtorrent/io.hpp" @@ -43,15 +49,6 @@ POSSIBILITY OF SUCH DAMAGE. using boost::bind; using namespace libtorrent; -enum { num_mappings = 2 }; - -namespace libtorrent -{ - // defined in upnp.cpp - bool is_local(address const& a); - address guess_local_address(asio::io_service&); -} - natpmp::natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb) : m_callback(cb) , m_currently_mapping(-1) @@ -59,99 +56,180 @@ natpmp::natpmp(io_service& ios, address const& listen_interface, portmap_callbac , m_socket(ios) , m_send_timer(ios) , m_refresh_timer(ios) + , m_next_refresh(-1) , m_disabled(false) { - m_mappings[0].protocol = 2; // tcp - m_mappings[1].protocol = 1; // udp - #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log.open("natpmp.log", std::ios::in | std::ios::out | std::ios::trunc); #endif rebind(listen_interface); } -void natpmp::rebind(address const& listen_interface) try +void natpmp::rebind(address const& listen_interface) { - address local = address_v4::any(); - if (listen_interface != address_v4::any()) - { - local = listen_interface; - } - else - { - local = guess_local_address(m_socket.io_service()); - - if (local == address_v4::any()) - { - throw std::runtime_error("local host is probably not on a NATed " - "network. disabling NAT-PMP"); - } - } + mutex_t::scoped_lock l(m_mutex); + error_code ec; + address gateway = get_default_gateway(m_socket.get_io_service(), ec); + if (ec) + { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " local ip: " << local.to_string() << std::endl; + m_log << time_now_string() << " failed to find default router: " + << ec.message() << std::endl; #endif - - if (!is_local(local)) - { - // the local address seems to be an external - // internet address. Assume it is not behind a NAT - throw std::runtime_error("local IP is not on a local network"); + disable("failed to find default router"); + return; } m_disabled = false; - asio::error_code ec; - udp::endpoint nat_endpoint(router_for_interface(local, ec), 5351); - if (ec) - throw std::runtime_error("cannot retrieve router address"); - + udp::endpoint nat_endpoint(gateway, 5351); if (nat_endpoint == m_nat_endpoint) return; m_nat_endpoint = nat_endpoint; #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "assuming router is at: " << m_nat_endpoint.address().to_string() << std::endl; + m_log << time_now_string() << " found router at: " + << m_nat_endpoint.address() << std::endl; #endif - m_socket.open(udp::v4()); - m_socket.bind(udp::endpoint(address_v4::any(), 0)); - - for (int i = 0; i < num_mappings; ++i) + m_socket.open(udp::v4(), ec); + if (ec) { - if (m_mappings[i].local_port == 0) + disable(ec.message().c_str()); + return; + } + m_socket.bind(udp::endpoint(address_v4::any(), 0), ec); + if (ec) + { + disable(ec.message().c_str()); + return; + } + + for (std::vector::iterator i = m_mappings.begin() + , end(m_mappings.end()); i != end; ++i) + { + if (i->protocol != none + || i->action != mapping_t::action_none) continue; - refresh_mapping(i); + i->action = mapping_t::action_add; + update_mapping(i - m_mappings.begin()); } } -catch (std::exception& e) + +void natpmp::disable(char const* message) { m_disabled = true; - std::stringstream msg; - msg << "NAT-PMP disabled: " << e.what(); -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << msg.str() << std::endl; -#endif - m_callback(0, 0, msg.str()); -}; -void natpmp::set_mappings(int tcp, int udp) + for (std::vector::iterator i = m_mappings.begin() + , end(m_mappings.end()); i != end; ++i) + { + if (i->protocol == none) continue; + i->protocol = none; + m_callback(i - m_mappings.begin(), 0, message); + } + +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + m_log << time_now_string() << " NAT-PMP disabled: " << message << std::endl; +#endif + close(); +} +void natpmp::delete_mapping(int index) { - if (m_disabled) return; - update_mapping(0, tcp); - update_mapping(1, udp); + TORRENT_ASSERT(index < int(m_mappings.size()) && index >= 0); + if (index >= int(m_mappings.size()) || index < 0) return; + mapping_t& m = m_mappings[index]; + + if (m.protocol == none) return; + + m.action = mapping_t::action_delete; + update_mapping(index); } -void natpmp::update_mapping(int i, int port) +int natpmp::add_mapping(protocol_type p, int external_port, int local_port) { - natpmp::mapping& m = m_mappings[i]; - if (port <= 0) return; - if (m.local_port != port) - m.need_update = true; + mutex_t::scoped_lock l(m_mutex); - m.local_port = port; - // prefer the same external port as the local port - if (m.external_port == 0) m.external_port = port; + if (m_disabled) return -1; + + std::vector::iterator i = std::find_if(m_mappings.begin() + , m_mappings.end(), boost::bind(&mapping_t::protocol, _1) == int(none)); + if (i == m_mappings.end()) + { + m_mappings.push_back(mapping_t()); + i = m_mappings.end() - 1; + } + i->protocol = p; + i->external_port = external_port; + i->local_port = local_port; + i->action = mapping_t::action_add; + + int mapping_index = i - m_mappings.begin(); + + update_mapping(mapping_index); + return mapping_index; +} + +void natpmp::try_next_mapping(int i) +{ +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + m_log << time_now_string() << " try_next_mapping [ " << i << " ]" << std::endl; +#endif + +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + ptime now = time_now(); + for (std::vector::iterator i = m_mappings.begin() + , end(m_mappings.end()); i != end; ++i) + { + m_log << " " << (i - m_mappings.begin()) << " [ " + "proto: " << (i->protocol == none ? "none" : i->protocol == tcp ? "tcp" : "udp") + << " port: " << i->external_port + << " local-port: " << i->local_port + << " action: " << (i->action == mapping_t::action_none ? "none" : i->action == mapping_t::action_add ? "add" : "delete") + << " ttl: " << total_seconds(i->expires - now) + << " ]" << std::endl; + } +#endif + + if (i < int(m_mappings.size()) - 1) + { + update_mapping(i + 1); + return; + } + + std::vector::iterator m = std::find_if( + m_mappings.begin(), m_mappings.end() + , boost::bind(&mapping_t::action, _1) != int(mapping_t::action_none)); + + if (m == m_mappings.end()) + { + if (m_abort) + { + error_code ec; + m_send_timer.cancel(ec); + m_socket.close(ec); + } +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + m_log << " done" << (m_abort?" shutting down":"") << std::endl; +#endif + return; + } + +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + m_log << " updating " << (m - m_mappings.begin()) << std::endl; +#endif + + update_mapping(m - m_mappings.begin()); +} + +void natpmp::update_mapping(int i) +{ + natpmp::mapping_t& m = m_mappings[i]; + if (m.action == mapping_t::action_none + || m.protocol == none) + { + try_next_mapping(i); + return; + } if (m_currently_mapping == -1) { @@ -164,14 +242,15 @@ void natpmp::update_mapping(int i, int port) } } -void natpmp::send_map_request(int i) try +void natpmp::send_map_request(int i) { using namespace libtorrent::detail; TORRENT_ASSERT(m_currently_mapping == -1 || m_currently_mapping == i); m_currently_mapping = i; - mapping& m = m_mappings[i]; + mapping_t& m = m_mappings[i]; + TORRENT_ASSERT(m.action != mapping_t::action_none); char buf[12]; char* out = buf; write_uint8(0, out); // NAT-PMP version @@ -179,220 +258,240 @@ void natpmp::send_map_request(int i) try write_uint16(0, out); // reserved write_uint16(m.local_port, out); // private port write_uint16(m.external_port, out); // requested public port - int ttl = m.external_port == 0 ? 0 : 3600; + int ttl = m.action == mapping_t::action_add ? 3600 : 0; write_uint32(ttl, out); // port mapping lifetime #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log << time_now_string() - << " ==> port map request: " << (m.protocol == 1 ? "udp" : "tcp") + << " ==> port map [" + << " action: " << (m.action == mapping_t::action_add ? "add" : "delete") << " " + << " proto: " << (m.protocol == udp ? "udp" : "tcp") << " local: " << m.local_port << " external: " << m.external_port - << " ttl: " << ttl << std::endl; + << " ttl: " << ttl << " ]" << std::endl; #endif - m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint); + error_code ec; + m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint, 0, ec); // linear back-off instead of exponential ++m_retry_count; - m_send_timer.expires_from_now(milliseconds(250 * m_retry_count)); + m_send_timer.expires_from_now(milliseconds(250 * m_retry_count), ec); m_send_timer.async_wait(bind(&natpmp::resend_request, self(), i, _1)); } -catch (std::exception& e) -{ - std::string err = e.what(); -}; -void natpmp::resend_request(int i, asio::error_code const& e) +void natpmp::resend_request(int i, error_code const& e) { if (e) return; + if (m_abort) return; + + mutex_t::scoped_lock l(m_mutex); if (m_currently_mapping != i) return; if (m_retry_count >= 9) { - m_mappings[i].need_update = false; + m_currently_mapping = -1; + m_mappings[i].action = mapping_t::action_none; // try again in two hours m_mappings[i].expires = time_now() + hours(2); + try_next_mapping(i); return; } send_map_request(i); } -void natpmp::on_reply(asio::error_code const& e +void natpmp::on_reply(error_code const& e , std::size_t bytes_transferred) { using namespace libtorrent::detail; if (e) return; - try + if (m_remote != m_nat_endpoint) { - - if (m_remote != m_nat_endpoint) - { - m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) - , m_remote, bind(&natpmp::on_reply, self(), _1, _2)); - return; - } - - m_send_timer.cancel(); - - TORRENT_ASSERT(m_currently_mapping >= 0); - int i = m_currently_mapping; - mapping& m = m_mappings[i]; - - char* in = m_response_buffer; - int version = read_uint8(in); - int cmd = read_uint8(in); - int result = read_uint16(in); - int time = read_uint32(in); - int private_port = read_uint16(in); - int public_port = read_uint16(in); - int lifetime = read_uint32(in); - - (void)time; // to remove warning - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " <== port map response: " << (cmd - 128 == 1 ? "udp" : "tcp") - << " local: " << private_port << " external: " << public_port - << " ttl: " << lifetime << std::endl; -#endif - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - if (version != 0) - { - m_log << "*** unexpected version: " << version << std::endl; - } -#endif - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - if (private_port != m.local_port) - { - m_log << "*** unexpected local port: " << private_port << std::endl; - } -#endif - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - if (cmd != 128 + m.protocol) - { - m_log << "*** unexpected protocol: " << (cmd - 128) << std::endl; - } -#endif - - if (public_port == 0 || lifetime == 0) - { - // this means the mapping was - // successfully closed - m.local_port = 0; - } - else - { - m.expires = time_now() + seconds(int(lifetime * 0.7f)); - m.external_port = public_port; - } - - if (result != 0) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "*** ERROR: " << result << std::endl; -#endif - std::stringstream errmsg; - errmsg << "NAT router reports error (" << result << ") "; - switch (result) - { - case 1: errmsg << "Unsupported protocol version"; break; - case 2: errmsg << "Not authorized to create port map (enable NAT-PMP on your router)"; break; - case 3: errmsg << "Network failure"; break; - case 4: errmsg << "Out of resources"; break; - case 5: errmsg << "Unsupported opcode"; break; - } - throw std::runtime_error(errmsg.str()); - } - - // don't report when we remove mappings - if (m.local_port != 0) - { - int tcp_port = 0; - int udp_port = 0; - if (m.protocol == 1) udp_port = m.external_port; - else tcp_port = public_port; - m_callback(tcp_port, udp_port, ""); - } - } - catch (std::exception& e) - { - // try again in two hours - m_mappings[m_currently_mapping].expires = time_now() + hours(2); - m_callback(0, 0, e.what()); + m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) + , m_remote, bind(&natpmp::on_reply, self(), _1, _2)); + return; } + + mutex_t::scoped_lock l(m_mutex); + + error_code ec; + m_send_timer.cancel(ec); + + TORRENT_ASSERT(m_currently_mapping >= 0); int i = m_currently_mapping; + mapping_t& m = m_mappings[i]; + + char* in = m_response_buffer; + int version = read_uint8(in); + int cmd = read_uint8(in); + int result = read_uint16(in); + int time = read_uint32(in); + int private_port = read_uint16(in); + int public_port = read_uint16(in); + int lifetime = read_uint32(in); + + (void)time; // to remove warning + +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + m_log << time_now_string() + << " <== port map [" + << " protocol: " << (cmd - 128 == 1 ? "udp" : "tcp") + << " local: " << private_port << " external: " << public_port + << " ttl: " << lifetime << " ]" << std::endl; +#endif + +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + if (version != 0) + { + m_log << "*** unexpected version: " << version << std::endl; + } +#endif + +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + if (private_port != m.local_port) + { + m_log << "*** unexpected local port: " << private_port << std::endl; + } +#endif + +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + if (cmd != 128 + m.protocol) + { + m_log << "*** unexpected protocol: " << (cmd - 128) << std::endl; + } +#endif + + if (public_port == 0 || lifetime == 0) + { + // this means the mapping was + // successfully closed + m.protocol = none; + } + else + { + m.expires = time_now() + seconds(int(lifetime * 0.7f)); + m.external_port = public_port; + } + + if (result != 0) + { +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + m_log << "*** ERROR: " << result << std::endl; +#endif + std::stringstream errmsg; + errmsg << "NAT router reports error (" << result << ") "; + switch (result) + { + case 1: errmsg << "Unsupported protocol version"; break; + case 2: errmsg << "Not authorized to create port map (enable NAT-PMP on your router)"; break; + case 3: errmsg << "Network failure"; break; + case 4: errmsg << "Out of resources"; break; + case 5: errmsg << "Unsupported opcode"; break; + } + m.expires = time_now() + hours(2); + m_callback(i, 0, errmsg.str()); + } + else if (m.action == mapping_t::action_add) + { + m_callback(i, m.external_port, ""); + } + m_currently_mapping = -1; - m_mappings[i].need_update = false; - m_send_timer.cancel(); + m.action = mapping_t::action_none; + m_send_timer.cancel(ec); update_expiration_timer(); try_next_mapping(i); } void natpmp::update_expiration_timer() { + if (m_abort) return; + ptime now = time_now(); +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + m_log << time_now_string() << " update_expiration_timer " << std::endl; + for (std::vector::iterator i = m_mappings.begin() + , end(m_mappings.end()); i != end; ++i) + { + m_log << " " << (i - m_mappings.begin()) << " [ " + "proto: " << (i->protocol == none ? "none" : i->protocol == tcp ? "tcp" : "udp") + << " port: " << i->external_port + << " local-port: " << i->local_port + << " action: " << (i->action == mapping_t::action_none ? "none" : i->action == mapping_t::action_add ? "add" : "delete") + << " ttl: " << total_seconds(i->expires - now) + << " ]" << std::endl; + } +#endif + ptime min_expire = now + seconds(3600); int min_index = -1; - for (int i = 0; i < num_mappings; ++i) - if (m_mappings[i].expires < min_expire - && m_mappings[i].local_port != 0) + for (std::vector::iterator i = m_mappings.begin() + , end(m_mappings.end()); i != end; ++i) + { + if (i->protocol == none + || i->action != mapping_t::action_none) continue; + if (i->expires < min_expire) { - min_expire = m_mappings[i].expires; - min_index = i; + min_expire = i->expires; + min_index = i - m_mappings.begin(); } + } + + // this is already the mapping we're waiting for + if (m_next_refresh == min_index) return; if (min_index >= 0) { - m_refresh_timer.expires_from_now(min_expire - now); +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + m_log << time_now_string() << " next expiration [" + " i: " << min_index + << " ttl: " << total_seconds(min_expire - time_now()) + << " ]" << std::endl; +#endif + error_code ec; + if (m_next_refresh >= 0) m_refresh_timer.cancel(ec); + m_refresh_timer.expires_from_now(min_expire - now, ec); m_refresh_timer.async_wait(bind(&natpmp::mapping_expired, self(), _1, min_index)); + m_next_refresh = min_index; } } -void natpmp::mapping_expired(asio::error_code const& e, int i) +void natpmp::mapping_expired(error_code const& e, int i) { if (e) return; + mutex_t::scoped_lock l(m_mutex); #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "*** mapping " << i << " expired, updating" << std::endl; + m_log << time_now_string() << " mapping expired [ i: " << i << " ]" << std::endl; #endif - refresh_mapping(i); -} - -void natpmp::refresh_mapping(int i) -{ - m_mappings[i].need_update = true; - if (m_currently_mapping == -1) - { - // the socket is not currently in use - // send out a mapping request - m_retry_count = 0; - send_map_request(i); - m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) - , m_remote, bind(&natpmp::on_reply, self(), _1, _2)); - } -} - -void natpmp::try_next_mapping(int i) -{ - ++i; - if (i >= num_mappings) i = 0; - if (m_mappings[i].need_update) - refresh_mapping(i); + m_mappings[i].action = mapping_t::action_add; + if (m_next_refresh == i) m_next_refresh = -1; + update_mapping(i); } void natpmp::close() { - asio::error_code ec; - m_socket.close(ec); + mutex_t::scoped_lock l(m_mutex); + m_abort = true; + error_code ec; +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + m_log << time_now_string() << " close" << std::endl; +#endif if (m_disabled) return; - for (int i = 0; i < num_mappings; ++i) + ptime now = time_now(); + for (std::vector::iterator i = m_mappings.begin() + , end(m_mappings.end()); i != end; ++i) { - if (m_mappings[i].local_port == 0) - continue; - m_mappings[i].external_port = 0; - refresh_mapping(i); +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + m_log << " " << (i - m_mappings.begin()) << " [ " + "proto: " << (i->protocol == none ? "none" : i->protocol == tcp ? "tcp" : "udp") + << " port: " << i->external_port + << " local-port: " << i->local_port + << " action: " << (i->action == mapping_t::action_none ? "none" : i->action == mapping_t::action_add ? "add" : "delete") + << " ttl: " << total_seconds(i->expires - now) + << " ]" << std::endl; +#endif + if (i->protocol == none) continue; + i->action = mapping_t::action_delete; } - m_refresh_timer.cancel(); - m_send_timer.cancel(); + m_refresh_timer.cancel(ec); + update_mapping(0); } diff --git a/libtorrent/src/parse_url.cpp b/libtorrent/src/parse_url.cpp new file mode 100644 index 000000000..2d54277c3 --- /dev/null +++ b/libtorrent/src/parse_url.cpp @@ -0,0 +1,132 @@ +/* + +Copyright (c) 2008, Arvid Norberg +All rights reserved. + +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. + +*/ + +#include "libtorrent/parse_url.hpp" +#include + +namespace libtorrent +{ + + // returns protocol, auth, hostname, port, path, error + boost::tuple + parse_url_components(std::string url) + { + std::string hostname; // hostname only + std::string auth; // user:pass + std::string protocol; // http or https for instance + char const* error = 0; + int port = 80; + + std::string::iterator at; + std::string::iterator colon; + std::string::iterator port_pos; + + // PARSE URL + std::string::iterator start = url.begin(); + // remove white spaces in front of the url + while (start != url.end() && (*start == ' ' || *start == '\t')) + ++start; + std::string::iterator end + = std::find(url.begin(), url.end(), ':'); + protocol.assign(start, end); + + if (protocol == "https") port = 443; + + if (end == url.end()) + { + error = "no protocol in url"; + goto exit; + } + ++end; + if (end == url.end() || *end != '/') + { + error = "incomplete protocol"; + goto exit; + } + ++end; + if (end == url.end() || *end != '/') + { + error = "incomplete protocol"; + goto exit; + } + ++end; + start = end; + + at = std::find(start, url.end(), '@'); + colon = std::find(start, url.end(), ':'); + end = std::find(start, url.end(), '/'); + + if (at != url.end() + && colon != url.end() + && colon < at + && at < end) + { + auth.assign(start, at); + start = at; + ++start; + } + + // this is for IPv6 addresses + if (start != url.end() && *start == '[') + { + port_pos = std::find(start, url.end(), ']'); + if (port_pos == url.end()) + { + error = "expected closing ']' for address"; + goto exit; + } + port_pos = std::find(port_pos, url.end(), ':'); + } + else + { + port_pos = std::find(start, url.end(), ':'); + } + + if (port_pos < end) + { + hostname.assign(start, port_pos); + ++port_pos; + port = atoi(std::string(port_pos, end).c_str()); + } + else + { + hostname.assign(start, end); + } + + start = end; +exit: + return boost::make_tuple(protocol, auth, hostname, port + , std::string(start, url.end()), error); + } + +} + diff --git a/libtorrent/src/pe_crypto.cpp b/libtorrent/src/pe_crypto.cpp index d9298e989..f20535610 100644 --- a/libtorrent/src/pe_crypto.cpp +++ b/libtorrent/src/pe_crypto.cpp @@ -42,29 +42,46 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { + namespace + { + const unsigned char dh_prime[96] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, + 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, + 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, + 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, + 0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63 + }; + + const unsigned char dh_generator[1] = { 2 }; + } // Set the prime P and the generator, generate local public key - DH_key_exchange::DH_key_exchange() + dh_key_exchange::dh_key_exchange() { - m_DH = DH_new(); - if (m_DH == 0) throw std::bad_alloc(); + m_dh = DH_new(); + if (m_dh == 0) return; - m_DH->p = BN_bin2bn(m_dh_prime, sizeof(m_dh_prime), NULL); - m_DH->g = BN_bin2bn(m_dh_generator, sizeof(m_dh_generator), NULL); - if (m_DH->p == 0 || m_DH->g == 0) + m_dh->p = BN_bin2bn(dh_prime, sizeof(dh_prime), 0); + m_dh->g = BN_bin2bn(dh_generator, sizeof(dh_generator), 0); + if (m_dh->p == 0 || m_dh->g == 0) { - DH_free(m_DH); - throw std::bad_alloc(); + DH_free(m_dh); + m_dh = 0; + return; } - m_DH->length = 160l; + m_dh->length = 160l; - TORRENT_ASSERT(sizeof(m_dh_prime) == DH_size(m_DH)); + TORRENT_ASSERT(sizeof(dh_prime) == DH_size(m_dh)); - if (DH_generate_key(m_DH) == 0 || m_DH->pub_key == 0) + if (DH_generate_key(m_dh) == 0 || m_dh->pub_key == 0) { - DH_free(m_DH); - throw std::bad_alloc(); + DH_free(m_dh); + m_dh = 0; + return; } // DH can generate key sizes that are smaller than the size of @@ -72,42 +89,53 @@ namespace libtorrent // the msb's of m_dh_local_key need to be zeroed // appropriately. int key_size = get_local_key_size(); - int len_dh = sizeof(m_dh_prime); // must equal DH_size(m_DH) + int len_dh = sizeof(dh_prime); // must equal DH_size(m_DH) if (key_size != len_dh) { TORRENT_ASSERT(key_size > 0 && key_size < len_dh); int pad_zero_size = len_dh - key_size; std::fill(m_dh_local_key, m_dh_local_key + pad_zero_size, 0); - BN_bn2bin(m_DH->pub_key, (unsigned char*)m_dh_local_key + pad_zero_size); + if (BN_bn2bin(m_dh->pub_key, (unsigned char*)m_dh_local_key + pad_zero_size) == 0) + { + DH_free(m_dh); + m_dh = 0; + return; + } } else - BN_bn2bin(m_DH->pub_key, (unsigned char*)m_dh_local_key); // TODO Check return value + { + if (BN_bn2bin(m_dh->pub_key, (unsigned char*)m_dh_local_key) == 0) + { + DH_free(m_dh); + m_dh = 0; + return; + } + } } - DH_key_exchange::~DH_key_exchange() + dh_key_exchange::~dh_key_exchange() { - TORRENT_ASSERT(m_DH); - DH_free(m_DH); + if (m_dh) DH_free(m_dh); } - char const* DH_key_exchange::get_local_key() const + char const* dh_key_exchange::get_local_key() const { return m_dh_local_key; } // compute shared secret given remote public key - void DH_key_exchange::compute_secret(char const* remote_pubkey) + int dh_key_exchange::compute_secret(char const* remote_pubkey) { TORRENT_ASSERT(remote_pubkey); BIGNUM* bn_remote_pubkey = BN_bin2bn ((unsigned char*)remote_pubkey, 96, NULL); - if (bn_remote_pubkey == 0) throw std::bad_alloc(); + if (bn_remote_pubkey == 0) return -1; char dh_secret[96]; int secret_size = DH_compute_key((unsigned char*)dh_secret - , bn_remote_pubkey, m_DH); - if (secret_size < 0 || secret_size > 96) throw std::bad_alloc(); + , bn_remote_pubkey, m_dh); + if (secret_size < 0 || secret_size > 96) return -1; if (secret_size != 96) { @@ -116,26 +144,14 @@ namespace libtorrent } std::copy(dh_secret, dh_secret + secret_size, m_dh_secret + 96 - secret_size); BN_free(bn_remote_pubkey); + return 0; } - char const* DH_key_exchange::get_secret() const + char const* dh_key_exchange::get_secret() const { return m_dh_secret; } - const unsigned char DH_key_exchange::m_dh_prime[96] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, - 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, - 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, - 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, - 0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63 - }; - - const unsigned char DH_key_exchange::m_dh_generator[1] = { 2 }; - } // namespace libtorrent #endif // #ifndef TORRENT_DISABLE_ENCRYPTION diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 0632e2cb9..fce7f1999 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -61,7 +61,6 @@ using libtorrent::aux::session_impl; namespace libtorrent { - // outbound connection peer_connection::peer_connection( session_impl& ses @@ -76,41 +75,31 @@ namespace libtorrent #endif m_ses(ses) , m_max_out_request_queue(m_ses.settings().max_out_request_queue) - , m_timeout(m_ses.settings().peer_timeout) , m_last_piece(time_now()) , m_last_request(time_now()) , m_last_incoming_request(min_time()) , m_last_unchoke(min_time()) - , m_packet_size(0) - , m_recv_pos(0) - , m_reading_bytes(0) , m_last_receive(time_now()) , m_last_sent(time_now()) + , m_requested(min_time()) + , m_timeout_extend(0) + , m_remote_dl_update(time_now()) + , m_connect(time_now()) + , m_became_uninterested(time_now()) + , m_became_uninteresting(time_now()) + , m_free_upload(0) + , m_downloaded_at_last_unchoke(0) + , m_disk_recv_buffer(ses, 0) , m_socket(s) , m_remote(endp) , m_torrent(tor) - , m_active(true) - , m_peer_interested(false) - , m_peer_choked(true) - , m_interesting(false) - , m_choked(true) - , m_failed(false) - , m_ignore_bandwidth_limits(false) - , m_have_all(false) , m_num_pieces(0) - , m_desired_queue_size(2) - , m_free_upload(0) - , m_assume_fifo(false) + , m_timeout(m_ses.settings().peer_timeout) + , m_packet_size(0) + , m_recv_pos(0) + , m_disk_recv_buffer_size(0) + , m_reading_bytes(0) , m_num_invalid_requests(0) - , m_disconnecting(false) - , m_became_uninterested(time_now()) - , m_became_uninteresting(time_now()) - , m_connecting(true) - , m_queued(true) - , m_writing(false) - , m_reading(false) - , m_prefer_whole_pieces(false) - , m_request_large_blocks(false) , m_priority(1) , m_upload_limit(bandwidth_limit::inf) , m_download_limit(bandwidth_limit::inf) @@ -119,34 +108,68 @@ namespace libtorrent , m_connection_ticket(-1) , m_remote_bytes_dled(0) , m_remote_dl_rate(0) - , m_remote_dl_update(time_now()) , m_outstanding_writing_bytes(0) + , m_download_rate_peak(0) + , m_upload_rate_peak(0) + , m_rtt(0) + , m_prefer_whole_pieces(0) + , m_desired_queue_size(2) , m_fast_reconnect(false) + , m_active(true) + , m_peer_interested(false) + , m_peer_choked(true) + , m_interesting(false) + , m_choked(true) + , m_failed(false) + , m_ignore_bandwidth_limits(false) + , m_have_all(false) + , m_disconnecting(false) + , m_connecting(true) + , m_queued(true) + , m_request_large_blocks(false) + , m_upload_only(false) + , m_snubbed(false) #ifndef NDEBUG , m_in_constructor(true) #endif { + m_channel_state[upload_channel] = peer_info::bw_idle; + m_channel_state[download_channel] = peer_info::bw_idle; + + TORRENT_ASSERT(peerinfo == 0 || peerinfo->banned == false); #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES std::fill(m_country, m_country + 2, 0); +#ifndef TORRENT_DISABLE_GEO_IP + if (m_ses.has_country_db()) + { + char const *country = m_ses.country_for_ip(m_remote.address()); + if (country != 0) + { + m_country[0] = country[0]; + m_country[1] = country[1]; + } + } #endif -#ifdef TORRENT_VERBOSE_LOGGING +#endif +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING m_logger = m_ses.create_log(m_remote.address().to_string() + "_" + boost::lexical_cast(m_remote.port()), m_ses.listen_port()); (*m_logger) << "*** OUTGOING CONNECTION\n"; #endif +#ifndef NDEBUG + piece_failed = false; +#endif +#ifndef TORRENT_DISABLE_GEO_IP + m_inet_as_name = m_ses.as_name_for_ip(m_remote.address()); +#endif - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); std::fill(m_peer_id.begin(), m_peer_id.end(), 0); - - if (t->ready_for_connections()) - init(); } // incoming connection peer_connection::peer_connection( session_impl& ses - , boost::shared_ptr s + , shared_ptr s , tcp::endpoint const& endp , policy::peer* peerinfo) : @@ -156,40 +179,30 @@ namespace libtorrent #endif m_ses(ses) , m_max_out_request_queue(m_ses.settings().max_out_request_queue) - , m_timeout(m_ses.settings().peer_timeout) , m_last_piece(time_now()) , m_last_request(time_now()) , m_last_incoming_request(min_time()) , m_last_unchoke(min_time()) - , m_packet_size(0) - , m_recv_pos(0) - , m_reading_bytes(0) , m_last_receive(time_now()) , m_last_sent(time_now()) - , m_socket(s) - , m_remote(endp) - , m_active(false) - , m_peer_interested(false) - , m_peer_choked(true) - , m_interesting(false) - , m_choked(true) - , m_failed(false) - , m_ignore_bandwidth_limits(false) - , m_have_all(false) - , m_num_pieces(0) - , m_desired_queue_size(2) - , m_free_upload(0) - , m_assume_fifo(false) - , m_num_invalid_requests(0) - , m_disconnecting(false) + , m_requested(min_time()) + , m_timeout_extend(0) + , m_remote_dl_update(time_now()) + , m_connect(time_now()) , m_became_uninterested(time_now()) , m_became_uninteresting(time_now()) - , m_connecting(false) - , m_queued(false) - , m_writing(false) - , m_reading(false) - , m_prefer_whole_pieces(false) - , m_request_large_blocks(false) + , m_free_upload(0) + , m_downloaded_at_last_unchoke(0) + , m_disk_recv_buffer(ses, 0) + , m_socket(s) + , m_remote(endp) + , m_num_pieces(0) + , m_timeout(m_ses.settings().peer_timeout) + , m_packet_size(0) + , m_recv_pos(0) + , m_disk_recv_buffer_size(0) + , m_reading_bytes(0) + , m_num_invalid_requests(0) , m_priority(1) , m_upload_limit(bandwidth_limit::inf) , m_download_limit(bandwidth_limit::inf) @@ -198,31 +211,121 @@ namespace libtorrent , m_connection_ticket(-1) , m_remote_bytes_dled(0) , m_remote_dl_rate(0) - , m_remote_dl_update(time_now()) , m_outstanding_writing_bytes(0) + , m_download_rate_peak(0) + , m_upload_rate_peak(0) + , m_rtt(0) + , m_prefer_whole_pieces(0) + , m_desired_queue_size(2) , m_fast_reconnect(false) + , m_active(false) + , m_peer_interested(false) + , m_peer_choked(true) + , m_interesting(false) + , m_choked(true) + , m_failed(false) + , m_ignore_bandwidth_limits(false) + , m_have_all(false) + , m_disconnecting(false) + , m_connecting(false) + , m_queued(false) + , m_request_large_blocks(false) + , m_upload_only(false) + , m_snubbed(false) #ifndef NDEBUG , m_in_constructor(true) #endif { - tcp::socket::non_blocking_io ioc(true); - m_socket->io_control(ioc); + m_channel_state[upload_channel] = peer_info::bw_idle; + m_channel_state[download_channel] = peer_info::bw_idle; + #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES std::fill(m_country, m_country + 2, 0); +#ifndef TORRENT_DISABLE_GEO_IP + if (m_ses.has_country_db()) + { + char const *country = m_ses.country_for_ip(m_remote.address()); + if (country != 0) + { + m_country[0] = country[0]; + m_country[1] = country[1]; + } + } +#endif #endif - m_remote = m_socket->remote_endpoint(); -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING error_code ec; - TORRENT_ASSERT(m_socket->remote_endpoint(ec) == remote()); + TORRENT_ASSERT(m_socket->remote_endpoint(ec) == m_remote || ec); m_logger = m_ses.create_log(remote().address().to_string(ec) + "_" + boost::lexical_cast(remote().port()), m_ses.listen_port()); (*m_logger) << "*** INCOMING CONNECTION\n"; #endif +#ifndef TORRENT_DISABLE_GEO_IP + m_inet_as_name = m_ses.as_name_for_ip(m_remote.address()); +#endif +#ifndef NDEBUG + piece_failed = false; +#endif std::fill(m_peer_id.begin(), m_peer_id.end(), 0); } + bool peer_connection::unchoke_compare(boost::intrusive_ptr const& p) const + { + TORRENT_ASSERT(p); + peer_connection const& rhs = *p; + + // first compare how many bytes they've sent us + size_type c1 = m_statistics.total_payload_download() - m_downloaded_at_last_unchoke; + size_type c2 = rhs.m_statistics.total_payload_download() - rhs.m_downloaded_at_last_unchoke; + if (c1 > c2) return true; + if (c1 < c2) return false; + + // if they are equal, compare how much we have uploaded + if (m_peer_info) c1 = m_peer_info->total_upload(); + else c1 = m_statistics.total_payload_upload(); + if (rhs.m_peer_info) c2 = rhs.m_peer_info->total_upload(); + else c2 = rhs.m_statistics.total_payload_upload(); + + return c1 < c2; + } + + void peer_connection::reset_choke_counters() + { + m_downloaded_at_last_unchoke = m_statistics.total_payload_download(); + } + + void peer_connection::start() + { + TORRENT_ASSERT(m_peer_info == 0 || m_peer_info->connection == this); + boost::shared_ptr t = m_torrent.lock(); + + if (!t) + { + tcp::socket::non_blocking_io ioc(true); + error_code ec; + m_socket->io_control(ioc, ec); + if (ec) + { + disconnect(ec.message().c_str()); + return; + } + m_remote = m_socket->remote_endpoint(ec); + if (ec) + { + disconnect(ec.message().c_str()); + return; + } + if (m_remote.address().is_v4()) + m_socket->set_option(type_of_service(m_ses.settings().peer_tos), ec); + } + else if (t->ready_for_connections()) + { + init(); + } + } + void peer_connection::update_interest() { INVARIANT_CHECK; @@ -231,15 +334,19 @@ namespace libtorrent TORRENT_ASSERT(t); bool interested = false; - const std::vector& we_have = t->pieces(); - for (int j = 0; j != (int)we_have.size(); ++j) + if (!t->is_finished()) { - if (!we_have[j] - && t->piece_priority(j) > 0 - && m_have_piece[j]) + piece_picker const& p = t->picker(); + int num_pieces = p.num_pieces(); + for (int j = 0; j != num_pieces; ++j) { - interested = true; - break; + if (!p.have_piece(j) + && t->piece_priority(j) > 0 + && m_have_piece[j]) + { + interested = true; + break; + } } } try @@ -333,12 +440,15 @@ namespace libtorrent TORRENT_ASSERT(t->ready_for_connections()); m_have_piece.resize(t->torrent_file().num_pieces(), m_have_all); + if (m_have_all) m_num_pieces = t->torrent_file().num_pieces(); // now that we have a piece_picker, - // update it with this peers pieces + // update it with this peer's pieces - int num_pieces = std::count(m_have_piece.begin(), m_have_piece.end(), true); - if (num_pieces == int(m_have_piece.size())) + TORRENT_ASSERT(m_num_pieces == std::count(m_have_piece.begin() + , m_have_piece.end(), true)); + + if (m_num_pieces == int(m_have_piece.size())) { #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << " *** THIS IS A SEED ***\n"; @@ -346,27 +456,26 @@ namespace libtorrent // if this is a web seed. we don't have a peer_info struct if (m_peer_info) m_peer_info->seed = true; // if we're a seed too, disconnect - if (t->is_finished()) + if (t->is_finished() && m_ses.settings().close_redundant_connections) { - throw std::runtime_error("seed to seed connection redundant, disconnecting"); + disconnect("seed to seed connection redundant"); + return; } - m_num_pieces = num_pieces; t->peer_has_all(); if (!t->is_finished()) t->get_policy().peer_is_interesting(*this); return; } - m_num_pieces = num_pieces; // if we're a seed, we don't keep track of piece availability if (!t->is_seed()) { + t->peer_has(m_have_piece); bool interesting = false; for (int i = 0; i < int(m_have_piece.size()); ++i) { if (m_have_piece[i]) { - t->peer_has(i); // if the peer has a piece and we don't, the peer is interesting if (!t->have_piece(i) && t->picker().piece_priority(i) != 0) @@ -384,14 +493,20 @@ namespace libtorrent TORRENT_ASSERT(!m_in_constructor); TORRENT_ASSERT(m_disconnecting); -#ifdef TORRENT_VERBOSE_LOGGING + m_disk_recv_buffer_size = 0; + +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING if (m_logger) { (*m_logger) << time_now_string() << " *** CONNECTION CLOSED\n"; } #endif + TORRENT_ASSERT(!m_ses.has_peer(this)); #ifndef NDEBUG + for (aux::session_impl::torrent_map::const_iterator i = m_ses.m_torrents.begin() + , end(m_ses.m_torrents.end()); i != end; ++i) + TORRENT_ASSERT(!i->second->has_peer(this)); if (m_peer_info) TORRENT_ASSERT(m_peer_info->connection == 0); @@ -401,12 +516,13 @@ namespace libtorrent void peer_connection::fast_reconnect(bool r) { - if (peer_info_struct() && peer_info_struct()->fast_reconnects > 1) return; + if (!peer_info_struct() || peer_info_struct()->fast_reconnects > 1) + return; m_fast_reconnect = r; peer_info_struct()->connected = time_now() - seconds(m_ses.settings().min_reconnect_time * m_ses.settings().max_failcount); - if (peer_info_struct()) ++peer_info_struct()->fast_reconnects; + ++peer_info_struct()->fast_reconnects; } void peer_connection::announce_piece(int index) @@ -422,7 +538,14 @@ namespace libtorrent // optimization, don't send have messages // to peers that already have the piece if (!m_ses.settings().send_redundant_have - && has_piece(index)) return; + && has_piece(index)) + { +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << time_now_string() + << " ==> HAVE [ piece: " << index << " ] SUPRESSED\n"; +#endif + return; + } #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() @@ -453,7 +576,7 @@ namespace libtorrent return m_request_queue; } - std::deque const& peer_connection::download_queue() const + std::deque const& peer_connection::download_queue() const { return m_download_queue; } @@ -468,7 +591,7 @@ namespace libtorrent m_statistics.add_stat(downloaded, uploaded); } - std::vector const& peer_connection::get_bitfield() const + bitfield const& peer_connection::get_bitfield() const { return m_have_piece; } @@ -481,7 +604,11 @@ namespace libtorrent for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) { +#ifdef BOOST_NO_EXCEPTIONS + (*i)->on_piece_pass(index); +#else try { (*i)->on_piece_pass(index); } catch (std::exception&) {} +#endif } #endif } @@ -494,15 +621,20 @@ namespace libtorrent for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) { +#ifdef BOOST_NO_EXCEPTIONS + (*i)->on_piece_failed(index); +#else try { (*i)->on_piece_failed(index); } catch (std::exception&) {} +#endif } #endif + if (is_disconnecting()) return; if (peer_info_struct()) { peer_info_struct()->on_parole = true; ++peer_info_struct()->hashfails; - int& trust_points = peer_info_struct()->trust_points; + boost::int8_t& trust_points = peer_info_struct()->trust_points; // we decrease more than we increase, to keep the // allowed failed/passed ratio low. @@ -563,7 +695,7 @@ namespace libtorrent if (t && t->is_aborted()) { -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << " *** the torrent has been aborted\n"; #endif t.reset(); @@ -572,7 +704,7 @@ namespace libtorrent if (!t) { // we couldn't find the torrent! -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << " *** couldn't find a torrent with the given info_hash: " << ih << "\n"; (*m_logger) << " torrents:\n"; session_impl::torrent_map const& torrents = m_ses.m_torrents; @@ -582,23 +714,37 @@ namespace libtorrent (*m_logger) << " " << i->second->torrent_file().info_hash() << "\n"; } #endif - throw std::runtime_error("got info-hash that is not in our session"); + disconnect("got invalid info-hash", 2); + return; } if (t->is_paused()) { // paused torrents will not accept // incoming connections -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << " rejected connection to paused torrent\n"; #endif - throw std::runtime_error("connection rejected by paused torrent"); + disconnect("connection rejected bacause torrent is paused"); + return; } TORRENT_ASSERT(m_torrent.expired()); // check to make sure we don't have another connection with the same // info_hash and peer_id. If we do. close this connection. +#ifndef NDEBUG + try + { +#endif t->attach_peer(this); +#ifndef NDEBUG + } + catch (std::exception& e) + { + std::cout << e.what() << std::endl; + TORRENT_ASSERT(false); + } +#endif if (m_disconnecting) return; m_torrent = wpt; @@ -615,7 +761,7 @@ namespace libtorrent // if we don't have valid metadata yet, // leave the vector unallocated TORRENT_ASSERT(m_num_pieces == 0); - std::fill(m_have_piece.begin(), m_have_piece.end(), false); + m_have_piece.clear_all(); TORRENT_ASSERT(!m_torrent.expired()); } @@ -652,12 +798,12 @@ namespace libtorrent if ((*i)->on_choke()) return; } #endif + if (is_disconnecting()) return; #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() << " <== CHOKE\n"; #endif m_peer_choked = true; - t->get_policy().choked(*this); if (peer_info_struct() == 0 || !peer_info_struct()->on_parole) { @@ -705,9 +851,12 @@ namespace libtorrent } #endif - std::deque::iterator i = std::find_if( + if (is_disconnecting()) return; + + std::deque::iterator i = std::find_if( m_download_queue.begin(), m_download_queue.end() - , bind(match_request, boost::cref(r), _1, t->block_size())); + , bind(match_request, boost::cref(r), bind(&pending_block::block, _1) + , t->block_size())); #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() @@ -717,7 +866,7 @@ namespace libtorrent piece_block b(-1, 0); if (i != m_download_queue.end()) { - b = *i; + b = i->block; m_download_queue.erase(i); // if the peer is in parole mode, keep the request @@ -731,7 +880,7 @@ namespace libtorrent p.abort_download(b); } } -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING else { (*m_logger) << time_now_string() @@ -755,12 +904,9 @@ namespace libtorrent m_suggested_pieces.erase(i); } - if (m_request_queue.empty()) + if (m_request_queue.empty() && m_download_queue.size() < 2) { - if (m_download_queue.size() < 2) - { - request_a_block(*t, *this); - } + request_a_block(*t, *this); send_block_requests(); } } @@ -788,6 +934,7 @@ namespace libtorrent } #endif + if (is_disconnecting()) return; if (t->have_piece(index)) return; if (m_suggested_pieces.size() > 9) @@ -823,6 +970,8 @@ namespace libtorrent (*m_logger) << time_now_string() << " <== UNCHOKE\n"; #endif m_peer_choked = false; + if (is_disconnecting()) return; + t->get_policy().unchoked(*this); } @@ -849,6 +998,7 @@ namespace libtorrent (*m_logger) << time_now_string() << " <== INTERESTED\n"; #endif m_peer_interested = true; + if (is_disconnecting()) return; t->get_policy().interested(*this); } @@ -873,11 +1023,12 @@ namespace libtorrent #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() << " <== NOT_INTERESTED\n"; #endif + m_peer_interested = false; + if (is_disconnecting()) return; boost::shared_ptr t = m_torrent.lock(); TORRENT_ASSERT(t); - m_peer_interested = false; t->get_policy().not_interested(*this); } @@ -900,25 +1051,47 @@ namespace libtorrent } #endif + if (is_disconnecting()) return; + #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() << " <== HAVE [ piece: " << index << "]\n"; #endif + if (!t->valid_metadata() && index > int(m_have_piece.size())) + { + if (index < 65536) + { + // if we don't have metadata + // and we might not have received a bitfield + // extend the bitmask to fit the new + // have message + m_have_piece.resize(index + 1, false); + } + else + { + // unless the index > 64k, in which case + // we just ignore it + return; + } + } + // if we got an invalid message, abort - if (index >= (int)m_have_piece.size() || index < 0) - throw protocol_error("got 'have'-message with higher index " - "than the number of pieces"); + if (index >= int(m_have_piece.size()) || index < 0) + { + disconnect("got 'have'-message with higher index than the number of pieces", 2); + return; + } if (m_have_piece[index]) { -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << " got redundant HAVE message for index: " << index << "\n"; #endif } else { - m_have_piece[index] = true; + m_have_piece.set_bit(index); // only update the piece_picker if // we have the metadata and if @@ -946,13 +1119,14 @@ namespace libtorrent } } - if (is_seed()) + if (upload_only()) { TORRENT_ASSERT(m_peer_info); - m_peer_info->seed = true; - if (t->is_finished()) + if (is_seed()) m_peer_info->seed = true; + if (t->is_finished() && m_ses.settings().close_redundant_connections) { - throw protocol_error("seed to seed connection redundant, disconnecting"); + disconnect("seed to seed connection redundant"); + return; } } } @@ -962,7 +1136,7 @@ namespace libtorrent // --------- BITFIELD ---------- // ----------------------------- - void peer_connection::incoming_bitfield(std::vector const& bitfield) + void peer_connection::incoming_bitfield(bitfield const& bits) { INVARIANT_CHECK; @@ -973,16 +1147,18 @@ namespace libtorrent for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) { - if ((*i)->on_bitfield(bitfield)) return; + if ((*i)->on_bitfield(bits)) return; } #endif + if (is_disconnecting()) return; + #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() << " <== BITFIELD "; - for (int i = 0; i < int(bitfield.size()); ++i) + for (int i = 0; i < int(bits.size()); ++i) { - if (bitfield[i]) (*m_logger) << "1"; + if (bits[i]) (*m_logger) << "1"; else (*m_logger) << "0"; } (*m_logger) << "\n"; @@ -991,12 +1167,15 @@ namespace libtorrent // if we don't have the metedata, we cannot // verify the bitfield size if (t->valid_metadata() - && (bitfield.size() / 8) != (m_have_piece.size() / 8)) - throw protocol_error("got bitfield with invalid size: " - + boost::lexical_cast(bitfield.size() / 8) - + "bytes. expected: " - + boost::lexical_cast(m_have_piece.size() / 8) - + "bytes"); + && (bits.size() / 8) != (m_have_piece.size() / 8)) + { + std::stringstream msg; + msg << "got bitfield with invalid size: " << (bits.size() / 8) + << "bytes. expected: " << (m_have_piece.size() / 8) + << " bytes"; + disconnect(msg.str().c_str(), 2); + return; + } // if we don't have metadata yet // just remember the bitmask @@ -1004,15 +1183,15 @@ namespace libtorrent // (since it doesn't exist yet) if (!t->ready_for_connections()) { - m_have_piece = bitfield; - m_num_pieces = std::count(bitfield.begin(), bitfield.end(), true); - if (m_peer_info) m_peer_info->seed = (m_num_pieces == int(bitfield.size())); + m_have_piece = bits; + m_num_pieces = bits.count(); + if (m_peer_info) m_peer_info->seed = (m_num_pieces == int(bits.size())); return; } TORRENT_ASSERT(t->valid_metadata()); - int num_pieces = std::count(bitfield.begin(), bitfield.end(), true); + int num_pieces = bits.count(); if (num_pieces == int(m_have_piece.size())) { #ifdef TORRENT_VERBOSE_LOGGING @@ -1021,12 +1200,13 @@ namespace libtorrent // if this is a web seed. we don't have a peer_info struct if (m_peer_info) m_peer_info->seed = true; // if we're a seed too, disconnect - if (t->is_finished()) + if (t->is_finished() && m_ses.settings().close_redundant_connections) { - throw protocol_error("seed to seed connection redundant, disconnecting"); + disconnect("seed to seed connection redundant, disconnecting"); + return; } - std::fill(m_have_piece.begin(), m_have_piece.end(), true); + m_have_piece.set_all(); m_num_pieces = num_pieces; t->peer_has_all(); if (!t->is_finished()) @@ -1037,49 +1217,32 @@ namespace libtorrent // let the torrent know which pieces the // peer has // if we're a seed, we don't keep track of piece availability + bool interesting = false; if (!t->is_seed()) { - bool interesting = false; + t->peer_has(bits); + for (int i = 0; i < (int)m_have_piece.size(); ++i) { - bool have = bitfield[i]; + bool have = bits[i]; if (have && !m_have_piece[i]) { - m_have_piece[i] = true; - ++m_num_pieces; - t->peer_has(i); if (!t->have_piece(i) && t->picker().piece_priority(i) != 0) interesting = true; } else if (!have && m_have_piece[i]) { // this should probably not be allowed - m_have_piece[i] = false; - --m_num_pieces; t->peer_lost(i); } } + } - if (interesting) t->get_policy().peer_is_interesting(*this); - } - else - { - for (int i = 0; i < (int)m_have_piece.size(); ++i) - { - bool have = bitfield[i]; - if (have && !m_have_piece[i]) - { - m_have_piece[i] = true; - ++m_num_pieces; - } - else if (!have && m_have_piece[i]) - { - // this should probably not be allowed - m_have_piece[i] = false; - --m_num_pieces; - } - } - } + m_have_piece = bits; + m_num_pieces = num_pieces; + + if (interesting) t->get_policy().peer_is_interesting(*this); + else if (upload_only()) disconnect("upload to upload connections"); } // ----------------------------- @@ -1100,12 +1263,13 @@ namespace libtorrent if ((*i)->on_request(r)) return; } #endif + if (is_disconnecting()) return; if (!t->valid_metadata()) { // if we don't have valid metadata yet, // we shouldn't get a request -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << time_now_string() << " <== UNEXPECTED_REQUEST [ " "piece: " << r.piece << " | " @@ -1114,32 +1278,32 @@ namespace libtorrent "i: " << m_peer_interested << " | " "t: " << t->torrent_file().piece_size(r.piece) << " | " "n: " << t->torrent_file().num_pieces() << " ]\n"; -#endif - write_reject_request(r); - return; - } - - if (int(m_requests.size()) > m_ses.settings().max_allowed_in_request_queue) - { - // don't allow clients to abuse our - // memory consumption. - // ignore requests if the client - // is making too many of them. -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== TOO MANY REQUESTS [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " | " - "i: " << m_peer_interested << " | " - "t: " << t->torrent_file().piece_size(r.piece) << " | " - "n: " << t->torrent_file().num_pieces() << " ]\n"; (*m_logger) << time_now_string() << " ==> REJECT_PIECE [ " "piece: " << r.piece << " | " "s: " << r.start << " | " "l: " << r.length << " ]\n"; +#endif + write_reject_request(r); + return; + } + + if (int(m_requests.size()) > m_ses.settings().max_allowed_in_request_queue) + { + // don't allow clients to abuse our + // memory consumption. + // ignore requests if the client + // is making too many of them. +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_logger) << time_now_string() + << " <== TOO MANY REQUESTS [ " + "piece: " << r.piece << " | " + "s: " << r.start << " | " + "l: " << r.length << " | " + "i: " << m_peer_interested << " | " + "t: " << t->torrent_file().piece_size(r.piece) << " | " + "n: " << t->torrent_file().num_pieces() << " ]\n"; (*m_logger) << time_now_string() << " ==> REJECT_PIECE [ " @@ -1173,7 +1337,7 @@ namespace libtorrent if (m_choked && m_accept_fast.find(r.piece) == m_accept_fast.end()) { write_reject_request(r); -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << time_now_string() << " *** REJECTING REQUEST [ peer choked and piece not in allowed fast set ]\n"; (*m_logger) << time_now_string() @@ -1192,7 +1356,7 @@ namespace libtorrent } else { -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << time_now_string() << " <== INVALID_REQUEST [ " "piece: " << r.piece << " | " @@ -1214,14 +1378,10 @@ namespace libtorrent write_reject_request(r); ++m_num_invalid_requests; - if (t->alerts().should_post(alert::debug)) + if (t->alerts().should_post()) { t->alerts().post_alert(invalid_request_alert( - r - , t->get_handle() - , m_remote - , m_peer_id - , "peer sent an illegal piece request")); + t->get_handle(), m_remote, m_peer_id, r)); } } } @@ -1267,18 +1427,34 @@ namespace libtorrent // ----------------------------- void peer_connection::incoming_piece(peer_request const& p, char const* data) + { + char* buffer = m_ses.allocate_disk_buffer(); + if (buffer == 0) + { + disconnect("out of memory"); + return; + } + disk_buffer_holder holder(m_ses, buffer); + std::memcpy(buffer, data, p.length); + incoming_piece(p, holder); + } + + void peer_connection::incoming_piece(peer_request const& p, disk_buffer_holder& data) { INVARIANT_CHECK; boost::shared_ptr t = m_torrent.lock(); TORRENT_ASSERT(t); + TORRENT_ASSERT(!m_disk_recv_buffer); + TORRENT_ASSERT(m_disk_recv_buffer_size == 0); + #ifdef TORRENT_CORRUPT_DATA // corrupt all pieces from certain peers if (m_remote.address().is_v4() && (m_remote.address().to_v4().to_ulong() & 0xf) == 0) { - const_cast(data[0]) = ~data[0]; + data.get()[0] = ~data.get()[0]; } #endif @@ -1289,11 +1465,14 @@ namespace libtorrent if ((*i)->on_piece(p, data)) return; } #endif + if (is_disconnecting()) return; #ifndef NDEBUG check_postcondition post_checker_(t); +#if !defined TORRENT_DISABLE_INVARIANT_CHECKS t->check_invariant(); #endif +#endif #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() @@ -1304,15 +1483,26 @@ namespace libtorrent "qs: " << m_desired_queue_size << " ]\n"; #endif + if (p.length == 0) + { + if (t->alerts().should_post()) + { + t->alerts().post_alert(peer_error_alert(t->get_handle(), m_remote + , m_peer_id, "peer sent 0 length piece")); + } + return; + } + if (!verify_piece(p)) { -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << time_now_string() << " <== INVALID_PIECE [ piece: " << p.piece << " | " "start: " << p.start << " | " "length: " << p.length << " ]\n"; #endif - throw protocol_error("got invalid piece packet"); + disconnect("got invalid piece packet", 2); + return; } // if we're already seeding, don't bother, @@ -1323,6 +1513,8 @@ namespace libtorrent return; } + ptime now = time_now(); + piece_picker& picker = t->picker(); piece_manager& fs = t->filesystem(); @@ -1332,49 +1524,20 @@ namespace libtorrent TORRENT_ASSERT(p.length == t->block_size() || p.length == t->torrent_file().total_size() % t->block_size()); - std::deque::iterator b - = std::find( + std::deque::iterator b + = std::find_if( m_download_queue.begin() , m_download_queue.end() - , block_finished); + , has_block(block_finished)); - if (b != m_download_queue.end()) + if (b == m_download_queue.end()) { - if (m_assume_fifo) + if (t->alerts().should_post()) { - for (std::deque::iterator i = m_download_queue.begin(); - i != b; ++i) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " *** SKIPPED_PIECE [ piece: " << i->piece_index << " | " - "b: " << i->block_index << " ] ***\n"; -#endif - // since this piece was skipped, clear it and allow it to - // be requested from other peers - // TODO: send cancel? - picker.abort_download(*i); - } - - // remove the request that just finished - // from the download queue plus the - // skipped blocks. - m_download_queue.erase(m_download_queue.begin(), b); - b = m_download_queue.begin(); - TORRENT_ASSERT(*b == block_finished); + t->alerts().post_alert(unwanted_block_alert(t->get_handle(), m_remote + , m_peer_id, block_finished.block_index, block_finished.piece_index)); } - } - else - { - if (t->alerts().should_post(alert::debug)) - { - t->alerts().post_alert( - peer_error_alert( - m_remote - , m_peer_id - , "got a block that was not in the request queue")); - } -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << " *** The block we just got was not in the " "request queue ***\n"; #endif @@ -1384,32 +1547,88 @@ namespace libtorrent return; } + for (std::deque::iterator i = m_download_queue.begin(); + i != b;) + { + +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_logger) << time_now_string() + << " *** SKIPPED_PIECE [ piece: " << i->block.piece_index << " | " + "b: " << i->block.block_index << " ] ***\n"; +#endif + + ++i->skipped; + // if the number of times a block is skipped by out of order + // blocks exceeds the size of the outstanding queue, assume that + // the other end dropped the request. + if (i->skipped > m_desired_queue_size) + { + if (m_ses.m_alerts.should_post()) + m_ses.m_alerts.post_alert(request_dropped_alert(t->get_handle() + , remote(), pid(), i->block.block_index, i->block.piece_index)); + picker.abort_download(i->block); + i = m_download_queue.erase(i); + } + else + { + ++i; + } + } + // if the block we got is already finished, then ignore it if (picker.is_downloaded(block_finished)) { t->received_redundant_data(p.length); m_download_queue.erase(b); + m_timeout_extend = 0; + + if (!m_download_queue.empty()) + m_requested = now; + request_a_block(*t, *this); send_block_requests(); return; } + if (total_seconds(now - m_requested) + < m_ses.settings().request_timeout + && m_snubbed) + { + m_snubbed = false; + if (m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(peer_unsnubbed_alert(t->get_handle() + , m_remote, m_peer_id)); + } + } + fs.async_write(p, data, bind(&peer_connection::on_disk_write_complete , self(), _1, _2, p, t)); m_outstanding_writing_bytes += p.length; - TORRENT_ASSERT(!m_reading); + TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle); m_download_queue.erase(b); + if (!m_download_queue.empty()) + { + m_timeout_extend = (std::max)(m_timeout_extend + - m_ses.settings().request_timeout, 0); + m_requested += seconds(m_ses.settings().request_timeout); + if (m_requested > now) m_requested = now; + } + else + { + m_timeout_extend = 0; + } + // did we request this block from any other peers? bool multi = picker.num_peers(block_finished) > 1; - picker.mark_as_writing(block_finished, peer_info_struct()); // if we requested this block from other peers, cancel it now if (multi) t->cancel_block(block_finished); -#ifndef NDEBUG +#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS t->check_invariant(); #endif request_a_block(*t, *this); @@ -1427,8 +1646,8 @@ namespace libtorrent TORRENT_ASSERT(m_outstanding_writing_bytes >= 0); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << time_now_string() << " *** DISK_WRITE_COMPLETE [ p: " - << p.piece << " o: " << p.start << " ]\n"; +// (*m_ses.m_logger) << time_now_string() << " *** DISK_WRITE_COMPLETE [ p: " +// << p.piece << " o: " << p.start << " ]\n"; #endif // in case the outstanding bytes just dropped down // to allow to receive more data @@ -1438,18 +1657,17 @@ namespace libtorrent if (ret == -1 || !t) { - if (t->has_picker()) t->picker().abort_download(block_finished); + if (t->has_picker()) t->picker().write_failed(block_finished); if (!t) { - m_ses.connection_failed(self(), remote(), j.str.c_str()); + disconnect(j.str.c_str()); return; } - if (t->alerts().should_post(alert::fatal)) + if (t->alerts().should_post()) { - std::string err = "torrent paused: disk write error, " + j.str; - t->alerts().post_alert(file_error_alert(t->get_handle(), err)); + t->alerts().post_alert(file_error_alert(j.error_file, t->get_handle(), j.str)); } t->pause(); return; @@ -1462,17 +1680,12 @@ namespace libtorrent TORRENT_ASSERT(p.piece == j.piece); TORRENT_ASSERT(p.start == j.offset); picker.mark_as_finished(block_finished, peer_info_struct()); - if (t->alerts().should_post(alert::debug)) + if (t->alerts().should_post()) { t->alerts().post_alert(block_finished_alert(t->get_handle(), - block_finished.block_index, block_finished.piece_index, "block finished")); + remote(), pid(), block_finished.block_index, block_finished.piece_index)); } -#ifndef NDEBUG - try - { -#endif - // did we just finish the piece? if (picker.is_piece_finished(p.piece)) { @@ -1483,15 +1696,6 @@ namespace libtorrent , p.piece, _1)); } -#ifndef NDEBUG - } - catch (std::exception const& e) - { - std::cerr << e.what() << std::endl; - TORRENT_ASSERT(false); - } -#endif - if (!t->is_seed() && !m_torrent.expired()) { // this is a free function defined in policy.cpp @@ -1516,6 +1720,7 @@ namespace libtorrent if ((*i)->on_cancel(r)) return; } #endif + if (is_disconnecting()) return; #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() @@ -1539,7 +1744,7 @@ namespace libtorrent } else { -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << time_now_string() << " *** GOT CANCEL NOT IN THE QUEUE\n"; #endif } @@ -1585,6 +1790,7 @@ namespace libtorrent if ((*i)->on_have_all()) return; } #endif + if (is_disconnecting()) return; m_have_all = true; @@ -1607,11 +1813,14 @@ namespace libtorrent #endif // if we're a seed too, disconnect - if (t->is_finished()) - throw protocol_error("seed to seed connection redundant, disconnecting"); + if (t->is_finished() && m_ses.settings().close_redundant_connections) + { + disconnect("seed to seed connection redundant, disconnecting"); + return; + } TORRENT_ASSERT(!m_have_piece.empty()); - std::fill(m_have_piece.begin(), m_have_piece.end(), true); + m_have_piece.set_all(); m_num_pieces = m_have_piece.size(); t->peer_has_all(); @@ -1627,13 +1836,13 @@ namespace libtorrent { INVARIANT_CHECK; - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); - #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() << " <== HAVE_NONE\n"; #endif + boost::shared_ptr t = m_torrent.lock(); + TORRENT_ASSERT(t); + #ifndef TORRENT_DISABLE_EXTENSIONS for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) @@ -1641,8 +1850,9 @@ namespace libtorrent if ((*i)->on_have_none()) return; } #endif - + if (is_disconnecting()) return; if (m_peer_info) m_peer_info->seed = false; + TORRENT_ASSERT(!m_have_piece.empty() || !t->ready_for_connections()); } @@ -1668,10 +1878,11 @@ namespace libtorrent if ((*i)->on_allowed_fast(index)) return; } #endif + if (is_disconnecting()) return; if (index < 0 || index >= int(m_have_piece.size())) { -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << time_now_string() << " <== INVALID_ALLOWED_FAST [ " << index << " | s: " << int(m_have_piece.size()) << " ]\n"; #endif @@ -1714,7 +1925,7 @@ namespace libtorrent void peer_connection::add_request(piece_block const& block) { - INVARIANT_CHECK; +// INVARIANT_CHECK; boost::shared_ptr t = m_torrent.lock(); TORRENT_ASSERT(t); @@ -1726,9 +1937,10 @@ namespace libtorrent TORRENT_ASSERT(block.block_index < t->torrent_file().piece_size(block.piece_index)); TORRENT_ASSERT(!t->picker().is_requested(block) || (t->picker().num_peers(block) > 0)); TORRENT_ASSERT(!t->have_piece(block.piece_index)); - TORRENT_ASSERT(std::find(m_download_queue.begin(), m_download_queue.end(), block) == m_download_queue.end()); - TORRENT_ASSERT(std::find(m_request_queue.begin(), m_request_queue.end(), block) == m_request_queue.end()); - + TORRENT_ASSERT(std::find_if(m_download_queue.begin(), m_download_queue.end() + , has_block(block)) == m_download_queue.end()); + TORRENT_ASSERT(std::find(m_request_queue.begin(), m_request_queue.end() + , block) == m_request_queue.end()); piece_picker::piece_state_t state; peer_speed_t speed = peer_speed(); @@ -1752,10 +1964,10 @@ namespace libtorrent if (!t->picker().mark_as_downloading(block, peer_info_struct(), state)) return; - if (t->alerts().should_post(alert::debug)) + if (t->alerts().should_post()) { t->alerts().post_alert(block_downloading_alert(t->get_handle(), - speedmsg, block.block_index, block.piece_index, "block downloading")); + remote(), pid(), speedmsg, block.block_index, block.piece_index)); } m_request_queue.push_back(block); @@ -1780,18 +1992,20 @@ namespace libtorrent // cancelled, then just ignore the cancel. if (!t->picker().is_requested(block)) return; - std::deque::iterator it - = std::find(m_download_queue.begin(), m_download_queue.end(), block); + std::deque::iterator it + = std::find_if(m_download_queue.begin(), m_download_queue.end(), has_block(block)); if (it == m_download_queue.end()) { - it = std::find(m_request_queue.begin(), m_request_queue.end(), block); + std::deque::iterator rit = std::find(m_request_queue.begin() + , m_request_queue.end(), block); + // when a multi block is received, it is cancelled // from all peers, so if this one hasn't requested // the block, just ignore to cancel it. - if (it == m_request_queue.end()) return; + if (rit == m_request_queue.end()) return; t->picker().abort_download(block); - m_request_queue.erase(it); + m_request_queue.erase(rit); // since we found it in the request queue, it means it hasn't been // sent yet, so we don't have to send a cancel. return; @@ -1836,22 +2050,28 @@ namespace libtorrent m_num_invalid_requests = 0; // reject the requests we have in the queue - std::for_each(m_requests.begin(), m_requests.end() - , bind(&peer_connection::write_reject_request, this, _1)); + // except the allowed fast pieces + for (std::deque::iterator i = m_requests.begin(); + i != m_requests.end();) + { + if (m_accept_fast.count(i->piece)) + { + ++i; + continue; + } + + peer_request const& r = *i; + write_reject_request(r); #ifdef TORRENT_VERBOSE_LOGGING - for (std::deque::iterator i = m_requests.begin() - , end(m_requests.end()); i != end; ++i) - { - peer_request const& r = *i; (*m_logger) << time_now_string() << " ==> REJECT_PIECE [ " "piece: " << r.piece << " | " "s: " << r.start << " | " "l: " << r.length << " ]\n"; - } #endif - m_requests.clear(); + i = m_requests.erase(i); + } } void peer_connection::send_unchoke() @@ -1905,6 +2125,8 @@ namespace libtorrent if ((int)m_download_queue.size() >= m_desired_queue_size) return; + bool empty_download_queue = m_download_queue.empty(); + while (!m_request_queue.empty() && (int)m_download_queue.size() < m_desired_queue_size) { @@ -1922,6 +2144,12 @@ namespace libtorrent r.length = block_size; m_request_queue.pop_front(); + if (t->is_seed()) continue; + // this can happen if a block times out, is re-requested and + // then arrives "unexpectedly" + if (t->picker().is_finished(block) || t->picker().is_downloaded(block)) + continue; + m_download_queue.push_back(block); /* #ifdef TORRENT_VERBOSE_LOGGING @@ -1975,6 +2203,7 @@ namespace libtorrent { if (handled = (*i)->write_request(r)) break; } + if (is_disconnecting()) return; if (!handled) { write_request(r); @@ -1997,33 +2226,55 @@ namespace libtorrent #endif } m_last_piece = time_now(); - } - - void close_socket_ignore_error(boost::shared_ptr s) - { - try { s->close(); } catch (std::exception&) {} + if (!m_download_queue.empty() + && empty_download_queue) + { + // This means we just added a request to this connection + m_requested = time_now(); + } } void peer_connection::timed_out() { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "CONNECTION TIMED OUT: " << m_remote.address().to_string() + TORRENT_ASSERT(m_connecting); + TORRENT_ASSERT(m_connection_ticket >= 0); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_ses.m_logger) << time_now_string() << " CONNECTION TIMED OUT: " << m_remote.address().to_string() << "\n"; #endif - m_ses.connection_failed(self(), m_remote, "timed out"); + disconnect("timed out: connect", 1); } - void peer_connection::disconnect() + // the error argument defaults to 0, which means deliberate disconnect + // 1 means unexpected disconnect/error + // 2 protocol error (client sent something invalid) + void peer_connection::disconnect(char const* message, int error) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - TORRENT_ASSERT(!m_in_constructor); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + switch (error) + { + case 0: + (*m_logger) << "*** CONNECTION CLOSED " << message << "\n"; + break; + case 1: + (*m_logger) << "*** CONNECTION FAILED " << message << "\n"; + break; + case 2: + (*m_logger) << "*** PEER ERROR " << message << "\n"; + break; + } +#endif + // we cannot do this in a constructor + TORRENT_ASSERT(m_in_constructor == false); + if (error > 0) m_failed = true; + if (m_disconnecting) return; boost::intrusive_ptr me(this); INVARIANT_CHECK; - if (m_disconnecting) return; if (m_connecting && m_connection_ticket >= 0) { m_ses.m_half_open.done(m_connection_ticket); @@ -2031,10 +2282,27 @@ namespace libtorrent } boost::shared_ptr t = m_torrent.lock(); + torrent_handle handle; + if (t) handle = t->get_handle(); + + if (message) + { + if (error > 1 && m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert( + peer_error_alert(handle, remote(), pid(), message)); + } + else if (error <= 1 && m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert( + peer_disconnected_alert(handle, remote(), pid(), message)); + } + } if (t) { // make sure we keep all the stats! + calc_ip_overhead(); t->add_stats(statistics()); if (t->has_picker()) @@ -2043,7 +2311,7 @@ namespace libtorrent while (!m_download_queue.empty()) { - picker.abort_download(m_download_queue.back()); + picker.abort_download(m_download_queue.back().block); m_download_queue.pop_back(); } while (!m_request_queue.empty()) @@ -2057,9 +2325,18 @@ namespace libtorrent m_torrent.reset(); } +#ifndef NDEBUG + // since this connection doesn't have a torrent reference + // no torrent should have a reference to this connection either + for (aux::session_impl::torrent_map::const_iterator i = m_ses.m_torrents.begin() + , end(m_ses.m_torrents.end()); i != end; ++i) + TORRENT_ASSERT(!i->second->has_peer(this)); +#endif + m_disconnecting = true; - m_ses.close_connection(me); - m_ses.m_io_service.post(boost::bind(&close_socket_ignore_error, m_socket)); + error_code ec; + m_socket->close(ec); + m_ses.close_connection(this, message); } void peer_connection::set_upload_limit(int limit) @@ -2113,6 +2390,11 @@ namespace libtorrent { TORRENT_ASSERT(!associated_torrent().expired()); + ptime now = time_now(); + + p.download_rate_peak = m_download_rate_peak; + p.upload_rate_peak = m_upload_rate_peak; + p.rtt = m_rtt; p.down_speed = statistics().download_rate(); p.up_speed = statistics().upload_rate(); p.payload_down_speed = statistics().download_payload_rate(); @@ -2120,6 +2402,14 @@ namespace libtorrent p.pid = pid(); p.ip = remote(); p.pending_disk_bytes = m_outstanding_writing_bytes; + p.send_quota = m_bandwidth_limit[upload_channel].quota_left(); + p.receive_quota = m_bandwidth_limit[download_channel].quota_left(); + if (m_download_queue.empty()) p.request_timeout = -1; + else p.request_timeout = total_seconds(m_requested - now) + m_ses.settings().request_timeout + + m_timeout_extend; +#ifndef TORRENT_DISABLE_GEO_IP + p.inet_as_name = m_inet_as_name; +#endif #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES p.country[0] = m_country[0]; @@ -2142,6 +2432,7 @@ namespace libtorrent p.load_balancing = total_free_upload(); p.download_queue_length = int(download_queue().size() + m_request_queue.size()); + p.requests_in_buffer = int(m_requests_in_buffer.size()); p.target_dl_queue_length = int(desired_queue_size()); p.upload_queue_length = int(upload_queue().size()); @@ -2161,7 +2452,6 @@ namespace libtorrent } p.pieces = get_bitfield(); - ptime now = time_now(); p.last_request = now - m_last_request; p.last_active = now - (std::max)(m_last_sent, m_last_receive); @@ -2170,14 +2460,18 @@ namespace libtorrent get_specific_peer_info(p); p.flags |= is_seed() ? peer_info::seed : 0; + p.flags |= m_snubbed ? peer_info::snubbed : 0; if (peer_info_struct()) { - p.source = peer_info_struct()->source; - p.failcount = peer_info_struct()->failcount; - p.num_hashfails = peer_info_struct()->hashfails; - p.flags |= peer_info_struct()->on_parole ? peer_info::on_parole : 0; - p.flags |= peer_info_struct()->optimistically_unchoked ? peer_info::optimistic_unchoke : 0; - p.remote_dl_rate = m_remote_dl_rate; + policy::peer* pi = peer_info_struct(); + p.source = pi->source; + p.failcount = pi->failcount; + p.num_hashfails = pi->hashfails; + p.flags |= pi->on_parole ? peer_info::on_parole : 0; + p.flags |= pi->optimistically_unchoked ? peer_info::optimistic_unchoke : 0; +#ifndef TORRENT_DISABLE_GEO_IP + p.inet_as = pi->inet_as->first; +#endif } else { @@ -2185,12 +2479,57 @@ namespace libtorrent p.failcount = 0; p.num_hashfails = 0; p.remote_dl_rate = 0; +#ifndef TORRENT_DISABLE_GEO_IP + p.inet_as = 0xffff; +#endif } + p.remote_dl_rate = m_remote_dl_rate; p.send_buffer_size = m_send_buffer.capacity(); p.used_send_buffer = m_send_buffer.size(); + p.receive_buffer_size = m_recv_buffer.capacity() + m_disk_recv_buffer_size; + p.used_receive_buffer = m_recv_pos; + p.write_state = m_channel_state[upload_channel]; + p.read_state = m_channel_state[download_channel]; } + // allocates a disk buffer of size 'disk_buffer_size' and replaces the + // end of the current receive buffer with it. i.e. the receive pos + // must be <= packet_size - disk_buffer_size + // the disk buffer can be accessed through release_disk_receive_buffer() + // when it is queried, the responsibility to free it is transferred + // to the caller + bool peer_connection::allocate_disk_receive_buffer(int disk_buffer_size) + { + INVARIANT_CHECK; + + TORRENT_ASSERT(m_packet_size > 0); + TORRENT_ASSERT(m_recv_pos <= m_packet_size - disk_buffer_size); + TORRENT_ASSERT(!m_disk_recv_buffer); + TORRENT_ASSERT(disk_buffer_size <= 16 * 1024); + + if (disk_buffer_size > 16 * 1024) + { + disconnect("invalid piece size", 2); + return false; + } + + m_disk_recv_buffer.reset(m_ses.allocate_disk_buffer()); + if (!m_disk_recv_buffer) + { + disconnect("out of memory"); + return false; + } + m_disk_recv_buffer_size = disk_buffer_size; + return true; + } + + char* peer_connection::release_disk_receive_buffer() + { + m_disk_recv_buffer_size = 0; + return m_disk_recv_buffer.release(); + } + void peer_connection::cut_receive_buffer(int size, int packet_size) { INVARIANT_CHECK; @@ -2210,20 +2549,30 @@ namespace libtorrent #endif m_packet_size = packet_size; - if (m_packet_size >= m_recv_pos) m_recv_buffer.resize(m_packet_size); + } + + void peer_connection::calc_ip_overhead() + { + m_statistics.calc_ip_overhead(); } void peer_connection::second_tick(float tick_interval) { + ptime now(time_now()); + boost::intrusive_ptr me(self()); + + // the invariant check must be run before me is destructed + // in case the peer got disconnected INVARIANT_CHECK; - try - { - - ptime now(time_now()); - boost::shared_ptr t = m_torrent.lock(); - TORRENT_ASSERT(t); + if (!t || m_disconnecting) + { + m_ses.m_half_open.done(m_connection_ticket); + m_connecting = false; + disconnect("torrent aborted"); + return; + } on_tick(); @@ -2233,13 +2582,117 @@ namespace libtorrent { (*i)->tick(); } + if (is_disconnecting()) return; #endif + // if the peer hasn't said a thing for a certain + // time, it is considered to have timed out + time_duration d; + d = now - m_last_receive; + if (d > seconds(m_timeout) && !m_connecting) + { +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_logger) << time_now_string() << " *** LAST ACTIVITY [ " + << total_seconds(d) << " seconds ago ] ***\n"; +#endif + disconnect("timed out: inactivity"); + return; + } + + // do not stall waiting for a handshake + if (!m_connecting + && in_handshake() + && d > seconds(m_ses.settings().handshake_timeout)) + { +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_logger) << time_now_string() << " *** NO HANDSHAKE [ waited " + << total_seconds(d) << " seconds ] ***\n"; +#endif + disconnect("timed out: no handshake"); + return; + } + + // disconnect peers that we unchoked, but + // they didn't send a request within 20 seconds. + // but only if we're a seed + d = now - (std::max)(m_last_unchoke, m_last_incoming_request); + if (!m_connecting + && m_requests.empty() + && !m_choked + && m_peer_interested + && t && t->is_finished() + && d > seconds(20)) + { +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_logger) << time_now_string() << " *** NO REQUEST [ t: " + << total_seconds(d) << " ] ***\n"; +#endif + disconnect("timed out: no request when unchoked"); + return; + } + + // if the peer hasn't become interested and we haven't + // become interested in the peer for 10 minutes, it + // has also timed out. + time_duration d1; + time_duration d2; + d1 = now - m_became_uninterested; + d2 = now - m_became_uninteresting; + time_duration time_limit = seconds( + m_ses.settings().inactivity_timeout); + + // don't bother disconnect peers we haven't been interested + // in (and that hasn't been interested in us) for a while + // unless we have used up all our connection slots + if (!m_interesting + && !m_peer_interested + && d1 > time_limit + && d2 > time_limit + && (m_ses.num_connections() >= m_ses.max_connections() + || (t && t->num_peers() >= t->max_connections()))) + { +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_logger) << time_now_string() << " *** MUTUAL NO INTEREST [ " + "t1: " << total_seconds(d1) << " | " + "t2: " << total_seconds(d2) << " ] ***\n"; +#endif + disconnect("timed out: no interest"); + return; + } + + if (!m_download_queue.empty() + && now > m_requested + seconds(m_ses.settings().request_timeout + + m_timeout_extend)) + { + snub_peer(); + } + + // if we haven't sent something in too long, send a keep-alive + keep_alive(); + m_ignore_bandwidth_limits = m_ses.settings().ignore_limits_on_local_network && on_local_network(); m_statistics.second_tick(tick_interval); + if (m_statistics.upload_payload_rate() > m_upload_rate_peak) + { + m_upload_rate_peak = m_statistics.upload_payload_rate(); + } + if (m_statistics.download_payload_rate() > m_download_rate_peak) + { + m_download_rate_peak = m_statistics.download_payload_rate(); +#ifndef TORRENT_DISABLE_GEO_IP + if (peer_info_struct()) + { + std::pair* as_stats = peer_info_struct()->inet_as; + if (as_stats && as_stats->second < m_download_rate_peak) + as_stats->second = m_download_rate_peak; + } +#endif + } + if (is_disconnecting()) return; + if (!t->valid_metadata()) return; // calculate the desired download queue size @@ -2254,60 +2707,35 @@ namespace libtorrent ? t->torrent_file().piece_length() : t->block_size(); TORRENT_ASSERT(block_size > 0); - m_desired_queue_size = static_cast(queue_time - * statistics().download_rate() / block_size); - if (m_desired_queue_size > m_max_out_request_queue) - m_desired_queue_size = m_max_out_request_queue; - if (m_desired_queue_size < min_request_queue) - m_desired_queue_size = min_request_queue; + if (m_snubbed) + { + m_desired_queue_size = 1; + } + else + { + m_desired_queue_size = static_cast(queue_time + * statistics().download_rate() / block_size); + if (m_desired_queue_size > m_max_out_request_queue) + m_desired_queue_size = m_max_out_request_queue; + if (m_desired_queue_size < min_request_queue) + m_desired_queue_size = min_request_queue; + } if (!m_download_queue.empty() - && now - m_last_piece > seconds(m_ses.settings().piece_timeout)) + && now - m_last_piece > seconds(m_ses.settings().piece_timeout + + m_timeout_extend)) { // this peer isn't sending the pieces we've // requested (this has been observed by BitComet) // in this case we'll clear our download queue and // re-request the blocks. -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << time_now_string() << " *** PIECE_REQUESTS TIMED OUT [ " << (int)m_download_queue.size() << " " << total_seconds(now - m_last_piece) << "] ***\n"; #endif - if (t->is_seed()) - { - m_download_queue.clear(); - m_request_queue.clear(); - } - else - { - piece_picker& picker = t->picker(); - - std::deque dl(m_download_queue); - for (std::deque::iterator i = dl.begin() - , end(dl.end()); i != end; ++i) - { - piece_block const& r = m_download_queue.back(); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> CANCEL [ piece: " << r.piece_index - << " | block: " << r.block_index - << " ]\n"; -#endif - write_cancel(t->to_req(r)); - } - while (!m_request_queue.empty()) - { - piece_block const& r = m_request_queue.back(); - picker.abort_download(r); - m_request_queue.pop_back(); - } - - m_assume_fifo = true; - - request_a_block(*t, *this); - send_block_requests(); - } + snub_peer(); } // If the client sends more data @@ -2365,14 +2793,76 @@ namespace libtorrent } fill_send_buffer(); - } - catch (std::exception& e) + } + + void peer_connection::snub_peer() + { + INVARIANT_CHECK; + + boost::shared_ptr t = m_torrent.lock(); + TORRENT_ASSERT(t); + + if (!m_snubbed) { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "**ERROR**: " << e.what() << "\n"; -#endif - m_ses.connection_failed(self(), remote(), e.what()); + m_snubbed = true; + if (m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(peer_snubbed_alert(t->get_handle() + , m_remote, m_peer_id)); + } } + m_desired_queue_size = 1; + + if (!t->has_picker()) return; + piece_picker& picker = t->picker(); + + piece_block r(-1, -1); + // time out the last request in the queue + if (!m_request_queue.empty()) + { + r = m_request_queue.back(); + m_request_queue.pop_back(); + } + else + { + TORRENT_ASSERT(!m_download_queue.empty()); + r = m_download_queue.back().block; + + // only time out a request if it blocks the piece + // from being completed (i.e. no free blocks to + // request from it) + piece_picker::downloading_piece p; + picker.piece_info(r.piece_index, p); + int free_blocks = picker.blocks_in_piece(r.piece_index) + - p.finished - p.writing - p.requested; + if (free_blocks > 0) + { + m_timeout_extend += m_ses.settings().request_timeout; + return; + } + + if (m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(block_timeout_alert(t->get_handle() + , remote(), pid(), r.block_index, r.piece_index)); + } + m_download_queue.pop_back(); + } + if (!m_download_queue.empty() || !m_request_queue.empty()) + m_timeout_extend += m_ses.settings().request_timeout; + + m_desired_queue_size = 2; + request_a_block(*t, *this); + m_desired_queue_size = 1; + + // abort the block after the new one has + // been requested in order to prevent it from + // picking the same block again, stalling the + // same piece indefinitely. + if (r != piece_block(-1, -1)) + picker.abort_download(r); + + send_block_requests(); } void peer_connection::fill_send_buffer() @@ -2386,8 +2876,9 @@ namespace libtorrent // otherwise there will be no end to how large it will be! int buffer_size_watermark = int(m_statistics.upload_rate()) / 2; - if (buffer_size_watermark < 1024) buffer_size_watermark = 1024; - else if (buffer_size_watermark > 80 * 1024) buffer_size_watermark = 80 * 1024; + if (buffer_size_watermark < 512) buffer_size_watermark = 512; + else if (buffer_size_watermark > m_ses.settings().send_buffer_watermark) + buffer_size_watermark = m_ses.settings().send_buffer_watermark; while (!m_requests.empty() && (send_buffer_size() + m_reading_bytes < buffer_size_watermark)) @@ -2415,26 +2906,20 @@ namespace libtorrent m_reading_bytes -= r.length; + disk_buffer_holder buffer(m_ses, j.buffer); + if (ret != r.length || m_torrent.expired()) { - if (j.buffer) m_ses.free_disk_buffer(j.buffer); boost::shared_ptr t = m_torrent.lock(); if (!t) { - m_ses.connection_failed(self(), remote(), j.str.c_str()); + disconnect(j.str.c_str()); return; } - if (t->alerts().should_post(alert::fatal)) - { - std::string err = "torrent paused: disk read error"; - if (!j.str.empty()) - { - err += ", "; - err += j.str; - } - t->alerts().post_alert(file_error_alert(t->get_handle(), err)); - } + if (t->alerts().should_post()) + t->alerts().post_alert(file_error_alert(j.error_file, t->get_handle(), j.str)); + t->set_error(j.str); t->pause(); return; } @@ -2445,7 +2930,7 @@ namespace libtorrent << " | l: " << r.length << " ]\n"; #endif - write_piece(r, j.buffer); + write_piece(r, buffer); setup_send(); } @@ -2458,16 +2943,14 @@ namespace libtorrent #endif m_bandwidth_limit[channel].assign(amount); + TORRENT_ASSERT(m_channel_state[channel] == peer_info::bw_global); + m_channel_state[channel] = peer_info::bw_idle; if (channel == upload_channel) { - TORRENT_ASSERT(m_writing); - m_writing = false; setup_send(); } else if (channel == download_channel) { - TORRENT_ASSERT(m_reading); - m_reading = false; setup_receive(); } } @@ -2493,7 +2976,7 @@ namespace libtorrent INVARIANT_CHECK; - if (m_writing) return; + if (m_channel_state[upload_channel] != peer_info::bw_idle) return; shared_ptr t = m_torrent.lock(); @@ -2509,15 +2992,16 @@ namespace libtorrent TORRENT_ASSERT(t); if (m_bandwidth_limit[upload_channel].max_assignable() > 0) { + int priority = is_interesting() * 2 + m_requests_in_buffer.size(); + // peers that we are not interested in are non-prioritized + m_channel_state[upload_channel] = peer_info::bw_torrent; + t->request_bandwidth(upload_channel, self() + , m_send_buffer.size(), priority); #ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ upload ]\n"; + (*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ upload prio: " + << priority << "]\n"; #endif - TORRENT_ASSERT(!m_writing); - // peers that we are not interested in are non-prioritized - m_writing = true; - t->request_bandwidth(upload_channel, self() - , is_interesting() * 2); } return; } @@ -2535,8 +3019,6 @@ namespace libtorrent return; } - TORRENT_ASSERT(!m_writing); - // send the actual buffer if (!m_send_buffer.empty()) { @@ -2553,7 +3035,7 @@ namespace libtorrent std::list const& vec = m_send_buffer.build_iovec(amount_to_send); m_socket->async_write_some(vec, bind(&peer_connection::on_send_data, self(), _1, _2)); - m_writing = true; + m_channel_state[upload_channel] = peer_info::bw_network; } } @@ -2563,10 +3045,7 @@ namespace libtorrent INVARIANT_CHECK; -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** SETUP_RECEIVE [ reading: " << (m_reading?"yes":"no") << "]\n"; -#endif - if (m_reading) return; + if (m_channel_state[download_channel] != peer_info::bw_idle) return; shared_ptr t = m_torrent.lock(); @@ -2580,8 +3059,10 @@ namespace libtorrent #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ download ]\n"; #endif - m_reading = true; - t->request_bandwidth(download_channel, self(), m_priority); + TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle); + m_channel_state[download_channel] = peer_info::bw_torrent; + t->request_bandwidth(download_channel, self() + , m_download_queue.size() * 16 * 1024 + 30, m_priority); } return; } @@ -2609,16 +3090,88 @@ namespace libtorrent TORRENT_ASSERT(m_recv_pos >= 0); TORRENT_ASSERT(m_packet_size > 0); - TORRENT_ASSERT(can_read()); #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() << " *** ASYNC_READ [ max: " << max_receive << " bytes ]\n"; #endif - m_socket->async_read_some(asio::buffer(&m_recv_buffer[m_recv_pos] - , max_receive), bind(&peer_connection::on_receive_data, self(), _1, _2)); - m_reading = true; + + int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size; + + if (int(m_recv_buffer.size()) < regular_buffer_size) + m_recv_buffer.resize(regular_buffer_size); + + if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos + max_receive) + { + // only receive into regular buffer + TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size())); + m_socket->async_read_some(asio::buffer(&m_recv_buffer[m_recv_pos] + , max_receive), bind(&peer_connection::on_receive_data, self(), _1, _2)); + } + else if (m_recv_pos >= regular_buffer_size) + { + // only receive into disk buffer + TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0); + TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size); + m_socket->async_read_some(asio::buffer(m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size + , max_receive) + , bind(&peer_connection::on_receive_data, self(), _1, _2)); + } + else + { + // receive into both regular and disk buffer + TORRENT_ASSERT(max_receive + m_recv_pos > regular_buffer_size); + TORRENT_ASSERT(m_recv_pos < regular_buffer_size); + TORRENT_ASSERT(max_receive - regular_buffer_size + + m_recv_pos <= m_disk_recv_buffer_size); + + boost::array vec; + vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos] + , regular_buffer_size - m_recv_pos); + vec[1] = asio::buffer(m_disk_recv_buffer.get() + , max_receive - regular_buffer_size + m_recv_pos); + m_socket->async_read_some(vec, bind(&peer_connection::on_receive_data + , self(), _1, _2)); + } + m_channel_state[download_channel] = peer_info::bw_network; } +#ifndef TORRENT_DISABLE_ENCRYPTION + + // returns the last 'bytes' from the receive buffer + std::pair peer_connection::wr_recv_buffers(int bytes) + { + TORRENT_ASSERT(bytes <= m_recv_pos); + + std::pair vec; + int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size; + TORRENT_ASSERT(regular_buffer_size >= 0); + if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos) + { + vec.first = buffer::interval(&m_recv_buffer[0] + + m_recv_pos - bytes, &m_recv_buffer[0] + m_recv_pos); + vec.second = buffer::interval(0,0); + } + else if (m_recv_pos - bytes >= regular_buffer_size) + { + vec.first = buffer::interval(m_disk_recv_buffer.get() + m_recv_pos + - regular_buffer_size - bytes, m_disk_recv_buffer.get() + m_recv_pos + - regular_buffer_size); + vec.second = buffer::interval(0,0); + } + else + { + TORRENT_ASSERT(m_recv_pos - bytes < regular_buffer_size); + TORRENT_ASSERT(m_recv_pos > regular_buffer_size); + vec.first = buffer::interval(&m_recv_buffer[0] + m_recv_pos - bytes + , &m_recv_buffer[0] + regular_buffer_size); + vec.second = buffer::interval(m_disk_recv_buffer.get() + , m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size); + } + TORRENT_ASSERT(vec.first.left() + vec.second.left() == bytes); + return vec; + } +#endif + void peer_connection::reset_recv_buffer(int packet_size) { TORRENT_ASSERT(packet_size > 0); @@ -2629,12 +3182,13 @@ namespace libtorrent } m_recv_pos = 0; m_packet_size = packet_size; - if (int(m_recv_buffer.size()) < m_packet_size) - m_recv_buffer.resize(m_packet_size); } - void peer_connection::send_buffer(char const* buf, int size) + void peer_connection::send_buffer(char const* buf, int size, int flags) { + if (flags == message_type_request) + m_requests_in_buffer.push_back(m_send_buffer.size() + size); + int free_space = m_send_buffer.space_in_last_buffer(); if (free_space > size) free_space = size; if (free_space > 0) @@ -2651,6 +3205,11 @@ namespace libtorrent if (size <= 0) return; std::pair buffer = m_ses.allocate_buffer(size); + if (buffer.first == 0) + { + disconnect("out of memory"); + return; + } TORRENT_ASSERT(buffer.second >= size); std::memcpy(buffer.first, buf, size); m_send_buffer.append_buffer(buffer.first, buffer.second, size @@ -2671,6 +3230,11 @@ namespace libtorrent if (insert == 0) { std::pair buffer = m_ses.allocate_buffer(size); + if (buffer.first == 0) + { + disconnect("out of memory"); + return buffer::interval(0, 0); + } TORRENT_ASSERT(buffer.second >= size); m_send_buffer.append_buffer(buffer.first, buffer.second, size , bind(&session_impl::free_buffer, boost::ref(m_ses), _1, buffer.second)); @@ -2708,26 +3272,28 @@ namespace libtorrent // -------------------------- // throws exception when the client should be disconnected - void peer_connection::on_receive_data(const asio::error_code& error - , std::size_t bytes_transferred) try + void peer_connection::on_receive_data(const error_code& error + , std::size_t bytes_transferred) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); INVARIANT_CHECK; - TORRENT_ASSERT(m_reading); - m_reading = false; + TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_network); + m_channel_state[download_channel] = peer_info::bw_idle; if (error) { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "**ERROR**: " << error.message() << "[in peer_connection::on_receive_data]\n"; +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_logger) << time_now_string() << " **ERROR**: " + << error.message() << "[in peer_connection::on_receive_data]\n"; #endif - set_failed(); on_receive(error, bytes_transferred); - throw std::runtime_error(error.message()); + disconnect(error.message().c_str()); + return; } + int max_receive = 0; do { #ifdef TORRENT_VERBOSE_LOGGING @@ -2744,8 +3310,9 @@ namespace libtorrent m_last_receive = time_now(); m_recv_pos += bytes_transferred; - TORRENT_ASSERT(m_recv_pos <= int(m_recv_buffer.size())); - + TORRENT_ASSERT(m_recv_pos <= int(m_recv_buffer.size() + + m_disk_recv_buffer_size)); + on_receive(error, bytes_transferred); TORRENT_ASSERT(m_packet_size > 0); @@ -2757,54 +3324,62 @@ namespace libtorrent buffer(m_packet_size).swap(m_recv_buffer); } - int max_receive = m_packet_size - m_recv_pos; + max_receive = m_packet_size - m_recv_pos; int quota_left = m_bandwidth_limit[download_channel].quota_left(); if (!m_ignore_bandwidth_limits && max_receive > quota_left) max_receive = quota_left; if (max_receive == 0) break; - asio::error_code ec; - bytes_transferred = m_socket->read_some(asio::buffer(&m_recv_buffer[m_recv_pos] - , max_receive), ec); + int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size; + + if (int(m_recv_buffer.size()) < regular_buffer_size) + m_recv_buffer.resize(regular_buffer_size); + + error_code ec; + if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos + max_receive) + { + // only receive into regular buffer + TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size())); + bytes_transferred = m_socket->read_some(asio::buffer(&m_recv_buffer[m_recv_pos] + , max_receive), ec); + } + else if (m_recv_pos >= regular_buffer_size) + { + // only receive into disk buffer + TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0); + TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size); + bytes_transferred = m_socket->read_some(asio::buffer(m_disk_recv_buffer.get() + + m_recv_pos - regular_buffer_size, (std::min)(m_packet_size + - m_recv_pos, max_receive)), ec); + } + else + { + // receive into both regular and disk buffer + TORRENT_ASSERT(max_receive + m_recv_pos > regular_buffer_size); + TORRENT_ASSERT(m_recv_pos < regular_buffer_size); + TORRENT_ASSERT(max_receive - regular_buffer_size + + m_recv_pos <= m_disk_recv_buffer_size); + + boost::array vec; + vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos] + , regular_buffer_size - m_recv_pos); + vec[1] = asio::buffer(m_disk_recv_buffer.get() + , (std::min)(m_disk_recv_buffer_size + , max_receive - regular_buffer_size + m_recv_pos)); + bytes_transferred = m_socket->read_some(vec, ec); + } if (ec && ec != asio::error::would_block) - throw asio::system_error(ec); + { + disconnect(ec.message().c_str()); + return; + } + if (ec == asio::error::would_block) break; } while (bytes_transferred > 0); setup_receive(); } - catch (file_error& e) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - boost::shared_ptr t = m_torrent.lock(); - if (!t) - { - m_ses.connection_failed(self(), remote(), e.what()); - return; - } - - if (t->alerts().should_post(alert::fatal)) - { - t->alerts().post_alert( - file_error_alert(t->get_handle() - , std::string("torrent paused: ") + e.what())); - } - t->pause(); - } - catch (std::exception& e) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(self(), remote(), e.what()); - } - catch (...) - { - // all exceptions should derive from std::exception - TORRENT_ASSERT(false); - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(self(), remote(), "connection failed for unknown reason"); - } bool peer_connection::can_write() const { @@ -2828,10 +3403,6 @@ namespace libtorrent && m_outstanding_writing_bytes < m_ses.settings().max_outstanding_disk_bytes_per_connection; -#if defined(TORRENT_VERBOSE_LOGGING) - (*m_logger) << time_now_string() << " *** can_read() " << (ret?"yes":"no") << " reading: " << m_reading << "\n"; -#endif - return ret; } @@ -2839,46 +3410,67 @@ namespace libtorrent { INVARIANT_CHECK; -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "CONNECTING: " << m_remote.address().to_string() + error_code ec; +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_ses.m_logger) << time_now_string() << " CONNECTING: " << m_remote.address().to_string(ec) << ":" << m_remote.port() << "\n"; #endif m_connection_ticket = ticket; boost::shared_ptr t = m_torrent.lock(); - if (!t || m_disconnecting) - { - m_ses.m_half_open.done(m_connection_ticket); - m_connecting = false; - disconnect(); - return; - } m_queued = false; TORRENT_ASSERT(m_connecting); - m_socket->open(t->get_interface().protocol()); + + if (!t) + { + disconnect("torrent aborted"); + return; + } + + m_socket->open(t->get_interface().protocol(), ec); + if (ec) + { + disconnect(ec.message().c_str()); + return; + } // set the socket to non-blocking, so that we can // read the entire buffer on each read event we get tcp::socket::non_blocking_io ioc(true); - m_socket->io_control(ioc); - m_socket->bind(t->get_interface()); + m_socket->io_control(ioc, ec); + if (ec) + { + disconnect(ec.message().c_str()); + return; + } + m_socket->bind(t->get_interface(), ec); + if (ec) + { + disconnect(ec.message().c_str()); + return; + } m_socket->async_connect(m_remote , bind(&peer_connection::on_connection_complete, self(), _1)); + m_connect = time_now(); - if (t->alerts().should_post(alert::debug)) + if (t->alerts().should_post()) { - t->alerts().post_alert(peer_error_alert( - m_remote, m_peer_id, "connecting to peer")); + t->alerts().post_alert(peer_connect_alert( + t->get_handle(), remote(), pid())); } } - void peer_connection::on_connection_complete(asio::error_code const& e) try + void peer_connection::on_connection_complete(error_code const& e) { + ptime completed = time_now(); + session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); INVARIANT_CHECK; + m_rtt = total_milliseconds(completed - m_connect); + if (m_disconnecting) return; m_connecting = false; @@ -2886,12 +3478,11 @@ namespace libtorrent if (e) { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "CONNECTION FAILED: " << m_remote.address().to_string() +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_ses.m_logger) << time_now_string() << " CONNECTION FAILED: " << m_remote.address().to_string() << ": " << e.message() << "\n"; #endif - set_failed(); - m_ses.connection_failed(self(), m_remote, e.message().c_str()); + disconnect(e.message().c_str(), 1); return; } @@ -2900,44 +3491,57 @@ namespace libtorrent // this means the connection just succeeded -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "COMPLETED: " << m_remote.address().to_string() << "\n"; + TORRENT_ASSERT(m_socket); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING + (*m_ses.m_logger) << time_now_string() << " COMPLETED: " << m_remote.address().to_string() + << " rtt = " << m_rtt << "\n"; #endif + error_code ec; + if (m_remote == m_socket->local_endpoint(ec)) + { + // if the remote endpoint is the same as the local endpoint, we're connected + // to ourselves + disconnect("connected to ourselves", 1); + return; + } + + if (m_remote.address().is_v4()) + { + error_code ec; + m_socket->set_option(type_of_service(m_ses.settings().peer_tos), ec); + } + on_connected(); setup_send(); setup_receive(); } - catch (std::exception& ex) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(self(), remote(), ex.what()); - } - catch (...) - { - // all exceptions should derive from std::exception - TORRENT_ASSERT(false); - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(self(), remote(), "connection failed for unkown reason"); - } // -------------------------- // SEND DATA // -------------------------- // throws exception when the client should be disconnected - void peer_connection::on_send_data(asio::error_code const& error - , std::size_t bytes_transferred) try + void peer_connection::on_send_data(error_code const& error + , std::size_t bytes_transferred) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); INVARIANT_CHECK; - TORRENT_ASSERT(m_writing); + TORRENT_ASSERT(m_channel_state[upload_channel] == peer_info::bw_network); m_send_buffer.pop_front(bytes_transferred); + + for (std::vector::iterator i = m_requests_in_buffer.begin() + , end(m_requests_in_buffer.end()); i != end; ++i) + *i -= bytes_transferred; + + while (!m_requests_in_buffer.empty() + && m_requests_in_buffer.front() <= 0) + m_requests_in_buffer.erase(m_requests_in_buffer.begin()); - m_writing = false; + m_channel_state[upload_channel] = peer_info::bw_idle; if (!m_ignore_bandwidth_limits) m_bandwidth_limit[upload_channel].use_quota(bytes_transferred); @@ -2948,11 +3552,11 @@ namespace libtorrent if (error) { -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << "**ERROR**: " << error.message() << " [in peer_connection::on_send_data]\n"; #endif - set_failed(); - throw std::runtime_error(error.message()); + disconnect(error.message().c_str()); + return; } if (m_disconnecting) return; @@ -2966,23 +3570,25 @@ namespace libtorrent setup_send(); } - catch (std::exception& e) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(self(), remote(), e.what()); - } - catch (...) - { - // all exceptions should derive from std::exception - TORRENT_ASSERT(false); - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(self(), remote(), "connection failed for unknown reason"); - } - #ifndef NDEBUG void peer_connection::check_invariant() const { + TORRENT_ASSERT(bool(m_disk_recv_buffer) == (m_disk_recv_buffer_size > 0)); + + boost::shared_ptr t = m_torrent.lock(); + if (m_disconnecting) + { + for (aux::session_impl::torrent_map::const_iterator i = m_ses.m_torrents.begin() + , end(m_ses.m_torrents.end()); i != end; ++i) + TORRENT_ASSERT(!i->second->has_peer((peer_connection*)this)); + TORRENT_ASSERT(!t); + } + else if (!m_in_constructor) + { + TORRENT_ASSERT(m_ses.has_peer((peer_connection*)this)); + } + for (int i = 0; i < 2; ++i) { // this peer is in the bandwidth history iff max_assignable < limit @@ -2990,12 +3596,23 @@ namespace libtorrent == m_ses.m_bandwidth_manager[i]->is_in_history(this) || m_bandwidth_limit[i].throttle() == bandwidth_limit::inf); } + + if (m_channel_state[download_channel] == peer_info::bw_torrent + || m_channel_state[download_channel] == peer_info::bw_global) + TORRENT_ASSERT(m_bandwidth_limit[download_channel].quota_left() == 0); + if (m_channel_state[upload_channel] == peer_info::bw_torrent + || m_channel_state[upload_channel] == peer_info::bw_global) + TORRENT_ASSERT(m_bandwidth_limit[upload_channel].quota_left() == 0); + std::set unique; - std::copy(m_download_queue.begin(), m_download_queue.end(), std::inserter(unique, unique.begin())); + std::transform(m_download_queue.begin(), m_download_queue.end() + , std::inserter(unique, unique.begin()), boost::bind(&pending_block::block, _1)); std::copy(m_request_queue.begin(), m_request_queue.end(), std::inserter(unique, unique.begin())); TORRENT_ASSERT(unique.size() == m_download_queue.size() + m_request_queue.size()); if (m_peer_info) { + TORRENT_ASSERT(m_peer_info->prev_amount_upload == 0); + TORRENT_ASSERT(m_peer_info->prev_amount_download == 0); TORRENT_ASSERT(m_peer_info->connection == this || m_peer_info->connection == 0); @@ -3003,9 +3620,38 @@ namespace libtorrent TORRENT_ASSERT(!is_choked()); } - boost::shared_ptr t = m_torrent.lock(); - if (!t) return; + if (!t) + { + // since this connection doesn't have a torrent reference + // no torrent should have a reference to this connection either + for (aux::session_impl::torrent_map::const_iterator i = m_ses.m_torrents.begin() + , end(m_ses.m_torrents.end()); i != end; ++i) + TORRENT_ASSERT(!i->second->has_peer((peer_connection*)this)); + return; + } + if (t->has_picker()) + { + std::map num_requests; + for (torrent::const_peer_iterator i = t->begin(); i != t->end(); ++i) + { + // make sure this peer is not a dangling pointer + TORRENT_ASSERT(m_ses.has_peer(*i)); + peer_connection const& p = *(*i); + for (std::deque::const_iterator i = p.request_queue().begin() + , end(p.request_queue().end()); i != end; ++i) + ++num_requests[*i]; + for (std::deque::const_iterator i = p.download_queue().begin() + , end(p.download_queue().end()); i != end; ++i) + ++num_requests[i->block]; + } + for (std::map::iterator i = num_requests.begin() + , end(num_requests.end()); i != end; ++i) + { + if (!t->picker().is_downloaded(i->first)) + TORRENT_ASSERT(t->picker().num_peers(i->first) == i->second); + } + } if (m_peer_info) { policy::const_iterator i; @@ -3036,13 +3682,17 @@ namespace libtorrent complete = false; break; } - if (complete) +/* +// this invariant is not valid anymore since the completion event +// might be queued in the io service + if (complete && !piece_failed) { disk_io_job ret = m_ses.m_disk_thread.find_job( &t->filesystem(), -1, i->index); TORRENT_ASSERT(ret.action == disk_io_job::hash || ret.action == disk_io_job::write); TORRENT_ASSERT(ret.piece == i->index); } +*/ } } // expensive when using checked iterators @@ -3091,94 +3741,6 @@ namespace libtorrent } #endif - bool peer_connection::has_timed_out() const - { - // TODO: the timeout should be called by an event - INVARIANT_CHECK; - - ptime now(time_now()); - - // if the socket is still connecting, don't - // consider it timed out. Because Windows XP SP2 - // may delay connection attempts. - if (m_connecting) return false; - - // if the peer hasn't said a thing for a certain - // time, it is considered to have timed out - time_duration d; - d = now - m_last_receive; - if (d > seconds(m_timeout)) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** LAST ACTIVITY [ " - << total_seconds(d) << " seconds ago ] ***\n"; -#endif - return true; - } - - // do not stall waiting for a handshake - if (in_handshake() && d > seconds(m_ses.settings().handshake_timeout)) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** NO HANDSHAKE [ waited " - << total_seconds(d) << " seconds ] ***\n"; -#endif - return true; - } - - // disconnect peers that we unchoked, but - // they didn't send a request within 20 seconds. - // but only if we're a seed - boost::shared_ptr t = m_torrent.lock(); - d = now - (std::max)(m_last_unchoke, m_last_incoming_request); - if (m_requests.empty() - && !m_choked - && m_peer_interested - && t && t->is_finished() - && d > seconds(20)) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** NO REQUEST [ t: " - << total_seconds(d) << " ] ***\n"; -#endif - return true; - } - - // TODO: as long as we have less than 95% of the - // global (or local) connection limit, connections should - // never time out for another reason - - // if the peer hasn't become interested and we haven't - // become interested in the peer for 10 minutes, it - // has also timed out. - time_duration d1; - time_duration d2; - d1 = now - m_became_uninterested; - d2 = now - m_became_uninteresting; - time_duration time_limit = seconds( - m_ses.settings().inactivity_timeout); - - // don't bother disconnect peers we haven't been intersted - // in (and that hasn't been interested in us) for a while - // unless we have used up all our connection slots - if (!m_interesting - && !m_peer_interested - && d1 > time_limit - && d2 > time_limit - && (m_ses.num_connections() >= m_ses.max_connections() - || (t && t->num_peers() >= t->max_connections()))) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** MUTUAL NO INTEREST [ " - "t1: " << total_seconds(d1) << " | " - "t2: " << total_seconds(d2) << " ] ***\n"; -#endif - return true; - } - - return false; - } - peer_connection::peer_speed_t peer_connection::peer_speed() { shared_ptr t = m_torrent.lock(); @@ -3212,7 +3774,7 @@ namespace libtorrent // if the last send has not completed yet, do not send a keep // alive - if (m_writing) return; + if (m_channel_state[upload_channel] != peer_info::bw_idle) return; #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() << " ==> KEEPALIVE\n"; diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp index dafca67d2..9e62e6379 100755 --- a/libtorrent/src/piece_picker.cpp +++ b/libtorrent/src/piece_picker.cpp @@ -37,11 +37,9 @@ POSSIBILITY OF SUCH DAMAGE. #include #include -// non-standard header, is_sorted() -//#include - #include "libtorrent/piece_picker.hpp" #include "libtorrent/aux_/session_impl.hpp" +#include "libtorrent/bitfield.hpp" #ifndef NDEBUG #include "libtorrent/peer_connection.hpp" @@ -49,24 +47,40 @@ POSSIBILITY OF SUCH DAMAGE. #endif //#define TORRENT_PIECE_PICKER_INVARIANT_CHECK INVARIANT_CHECK +//#define TORRENT_NO_EXPENSIVE_INVARIANT_CHECK #define TORRENT_PIECE_PICKER_INVARIANT_CHECK +//#define TORRENT_PICKER_LOG + namespace libtorrent { - piece_picker::piece_picker(int blocks_per_piece, int total_num_blocks) - : m_piece_info(2) - , m_piece_map((total_num_blocks + blocks_per_piece-1) / blocks_per_piece) + piece_picker::piece_picker() + : m_seeds(0) + , m_priority_boundries(1, int(m_pieces.size())) , m_num_filtered(0) , m_num_have_filtered(0) , m_num_have(0) - , m_sequenced_download_threshold(100) + , m_sequential_download(-1) + , m_dirty(false) + { +#ifdef TORRENT_PICKER_LOG + std::cerr << "new piece_picker" << std::endl; +#endif +#ifndef NDEBUG + check_invariant(); +#endif + } + + void piece_picker::init(int blocks_per_piece, int total_num_blocks) { TORRENT_ASSERT(blocks_per_piece > 0); TORRENT_ASSERT(total_num_blocks >= 0); -#ifndef NDEBUG - m_files_checked_called = false; -#endif + + // allocate the piece_map to cover all pieces + // and make them invalid (as if we don't have a single piece) + m_piece_map.resize((total_num_blocks + blocks_per_piece-1) / blocks_per_piece + , piece_pos(0, 0)); // the piece index is stored in 20 bits, which limits the allowed // number of pieces somewhat @@ -78,63 +92,29 @@ namespace libtorrent if (m_blocks_in_last_piece == 0) m_blocks_in_last_piece = blocks_per_piece; TORRENT_ASSERT(m_blocks_in_last_piece <= m_blocks_per_piece); - - // allocate the piece_map to cover all pieces - // and make them invalid (as if we don't have a single piece) - std::fill(m_piece_map.begin(), m_piece_map.end() - , piece_pos(0, 0)); - m_num_have = 0; } - // pieces is a bitmask with the pieces we have - void piece_picker::files_checked( - std::vector const& pieces - , std::vector const& unfinished - , std::vector& verify_pieces) + void piece_picker::sequential_download(bool sd) { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; -#ifndef NDEBUG - m_files_checked_called = true; -#endif - for (std::vector::const_iterator i = pieces.begin(); - i != pieces.end(); ++i) - { - int index = static_cast(i - pieces.begin()); - piece_pos& p = m_piece_map[index]; - if (*i) - { - ++m_num_have; - p.set_have(); - if (p.filtered()) - { - ++m_num_have_filtered; - TORRENT_ASSERT(m_num_filtered > 0); - --m_num_filtered; - } - } - else - { - p.index = 0; - } - } + if (sd == sequential_download()) return; - // if we have fast resume info - // use it - if (!unfinished.empty()) + TORRENT_PIECE_PICKER_INVARIANT_CHECK; + + if (sd) { - for (std::vector::const_iterator i - = unfinished.begin(); i != unfinished.end(); ++i) - { - for (int j = 0; j < m_blocks_per_piece; ++j) - { - if (i->info[j].state == block_info::state_finished) - mark_as_finished(piece_block(i->index, j), 0); - } - if (is_piece_finished(i->index)) - { - verify_pieces.push_back(i->index); - } - } + std::vector().swap(m_pieces); + std::vector().swap(m_priority_boundries); + + // initialize m_sdquential_download + m_sequential_download = 0; + for (std::vector::const_iterator i = m_piece_map.begin() + , end(m_piece_map.end()); i != end && (i->have() || i->filtered()); + ++i, ++m_sequential_download); + } + else + { + m_sequential_download = -1; + m_dirty = true; } } @@ -167,68 +147,6 @@ namespace libtorrent st.finished = 0; } - void piece_picker::set_sequenced_download_threshold( - int sequenced_download_threshold) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - - if (sequenced_download_threshold == m_sequenced_download_threshold) - return; - - TORRENT_ASSERT(sequenced_download_threshold > 0); - if (sequenced_download_threshold <= 0) return; - - int old_limit = m_sequenced_download_threshold; - m_sequenced_download_threshold = sequenced_download_threshold; - - for (std::vector::iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i) - { - if (i->priority(old_limit) != i->priority(m_sequenced_download_threshold)) - { - piece_pos& p = *i; - int prev_priority = p.priority(old_limit); - if (prev_priority == 0) continue; - move(prev_priority, p.index); - } - } - - typedef std::vector info_t; - - if (old_limit < sequenced_download_threshold) - { - // the threshold was incremented, in case - // the previous max availability was reached - // we need to shuffle that bucket, if not, we - // don't have to do anything - if (int(m_piece_info.size()) > old_limit * 2) - { - info_t& in = m_piece_info[old_limit * 2]; - std::random_shuffle(in.begin(), in.end()); - int c = 0; - for (info_t::iterator i = in.begin() - , end(in.end()); i != end; ++i) - { - m_piece_map[*i].index = c++; - TORRENT_ASSERT(m_piece_map[*i].priority(old_limit) == old_limit * 2); - } - } - } - else if (int(m_piece_info.size()) > sequenced_download_threshold * 2) - { - info_t& in = m_piece_info[sequenced_download_threshold * 2]; - std::sort(in.begin(), in.end()); - int c = 0; - for (info_t::iterator i = in.begin() - , end(in.end()); i != end; ++i) - { - m_piece_map[*i].index = c++; - TORRENT_ASSERT(m_piece_map[*i].priority( - sequenced_download_threshold) == sequenced_download_threshold * 2); - } - } - } - piece_picker::downloading_piece& piece_picker::add_download_piece() { int num_downloads = m_downloads.size(); @@ -276,27 +194,65 @@ namespace libtorrent #ifndef NDEBUG void piece_picker::verify_pick(std::vector const& picked - , std::vector const& bitfield) const + , bitfield const& bits) const { - TORRENT_ASSERT(bitfield.size() == m_piece_map.size()); + TORRENT_ASSERT(bits.size() == m_piece_map.size()); for (std::vector::const_iterator i = picked.begin() , end(picked.end()); i != end; ++i) { TORRENT_ASSERT(i->piece_index >= 0); - TORRENT_ASSERT(i->piece_index < int(bitfield.size())); - TORRENT_ASSERT(bitfield[i->piece_index]); + TORRENT_ASSERT(i->piece_index < int(bits.size())); + TORRENT_ASSERT(bits[i->piece_index]); TORRENT_ASSERT(!m_piece_map[i->piece_index].have()); } } + void piece_picker::verify_priority(int range_start, int range_end, int prio) const + { + TORRENT_ASSERT(range_start <= range_end); + TORRENT_ASSERT(range_end <= int(m_pieces.size())); + for (std::vector::const_iterator i = m_pieces.begin() + range_start + , end(m_pieces.begin() + range_end); i != end; ++i) + { + int index = *i; + TORRENT_ASSERT(index >= 0); + TORRENT_ASSERT(index < int(m_piece_map.size())); + int p = m_piece_map[index].priority(this); + TORRENT_ASSERT(p == prio); + } + } + + void piece_picker::print_pieces() const + { + for (std::vector::const_iterator i = m_priority_boundries.begin() + , end(m_priority_boundries.end()); i != end; ++i) + { + std::cerr << *i << " "; + } + std::cout << std::endl; + int index = 0; + std::vector::const_iterator j = m_priority_boundries.begin(); + for (std::vector::const_iterator i = m_pieces.begin() + , end(m_pieces.end()); i != end; ++i, ++index) + { + if (*i == -1) break; + while (j != m_priority_boundries.end() && *j <= index) + { + std::cerr << "| "; + ++j; + } + std::cerr << *i << "(" << m_piece_map[*i].index << ") "; + } + std::cerr << std::endl; + } + void piece_picker::check_invariant(const torrent* t) const { TORRENT_ASSERT(sizeof(piece_pos) == 4); TORRENT_ASSERT(m_num_have >= 0); TORRENT_ASSERT(m_num_have_filtered >= 0); TORRENT_ASSERT(m_num_filtered >= 0); - - TORRENT_ASSERT(m_piece_info.empty() || m_piece_info[0].empty()); + TORRENT_ASSERT(m_seeds >= 0); if (!m_downloads.empty()) { @@ -312,9 +268,6 @@ namespace libtorrent if (t != 0) TORRENT_ASSERT((int)m_piece_map.size() == t->torrent_file().num_pieces()); - for (int i = m_sequenced_download_threshold * 2 + 1; i < int(m_piece_info.size()); ++i) - TORRENT_ASSERT(m_piece_info[i].empty()); - for (std::vector::const_iterator i = m_downloads.begin() , end(m_downloads.end()); i != end; ++i) { @@ -328,17 +281,18 @@ namespace libtorrent if (i->info[k].state == block_info::state_finished) { ++num_finished; - continue; + TORRENT_ASSERT(i->info[k].num_peers == 0); } - if (i->info[k].state == block_info::state_requested) + else if (i->info[k].state == block_info::state_requested) { ++num_requested; blocks_requested = true; TORRENT_ASSERT(i->info[k].num_peers > 0); } - if (i->info[k].state == block_info::state_writing) + else if (i->info[k].state == block_info::state_writing) { ++num_writing; + TORRENT_ASSERT(i->info[k].num_peers == 0); } } TORRENT_ASSERT(blocks_requested == (i->state != none)); @@ -346,7 +300,32 @@ namespace libtorrent TORRENT_ASSERT(num_writing == i->writing); TORRENT_ASSERT(num_finished == i->finished); } +#ifdef TORRENT_NO_EXPENSIVE_INVARIANT_CHECK + return; +#endif + if (m_sequential_download == -1 && !m_dirty) + { + TORRENT_ASSERT(!m_priority_boundries.empty()); + int prio = 0; + int start = 0; + for (std::vector::const_iterator i = m_priority_boundries.begin() + , end(m_priority_boundries.end()); i != end; ++i) + { + verify_priority(start, *i, prio); + ++prio; + start = *i; + } + TORRENT_ASSERT(m_priority_boundries.back() == int(m_pieces.size())); + } + else if (m_sequential_download >= 0) + { + int index = 0; + for (std::vector::const_iterator i = m_piece_map.begin() + , end(m_piece_map.end()); i != end && (i->have() || i->filtered()); + ++i, ++index); + TORRENT_ASSERT(m_sequential_download == index); + } int num_filtered = 0; int num_have_filtered = 0; @@ -355,14 +334,16 @@ namespace libtorrent i != m_piece_map.end(); ++i) { int index = static_cast(i - m_piece_map.begin()); - if (i->filtered()) + piece_pos const& p = *i; + + if (p.filtered()) { - if (i->index != piece_pos::we_have_index) + if (p.index != piece_pos::we_have_index) ++num_filtered; else ++num_have_filtered; } - if (i->index == piece_pos::we_have_index) + if (p.index == piece_pos::we_have_index) ++num_have; #if 0 @@ -400,46 +381,39 @@ namespace libtorrent } #endif - if (i->index == piece_pos::we_have_index) + if (p.index == piece_pos::we_have_index) { TORRENT_ASSERT(t == 0 || t->have_piece(index)); - TORRENT_ASSERT(i->downloading == 0); -/* - // make sure there's no entry - // with this index. (there shouldn't - // be since the piece_map is piece_pos::we_have_index) - for (int i = 0; i < int(m_piece_info.size()); ++i) - { - for (int j = 0; j < int(m_piece_info[i].size()); ++j) - { - TORRENT_ASSERT(m_piece_info[i][j] != index); - } - } -*/ + TORRENT_ASSERT(p.downloading == 0); } - else - { - if (t != 0) - TORRENT_ASSERT(!t->have_piece(index)); - int prio = i->priority(m_sequenced_download_threshold); - TORRENT_ASSERT(prio < int(m_piece_info.size())); - if (prio > 0) + if (t != 0) + TORRENT_ASSERT(!t->have_piece(index)); + + if (m_sequential_download == -1 && !m_dirty) + { + int prio = p.priority(this); + TORRENT_ASSERT(prio < int(m_priority_boundries.size()) + || m_dirty); + if (prio >= 0) { - const std::vector& vec = m_piece_info[prio]; - assert (i->index < vec.size()); - TORRENT_ASSERT(vec[i->index] == index); + TORRENT_ASSERT(p.index < m_pieces.size()); + TORRENT_ASSERT(m_pieces[p.index] == index); } -/* - for (int k = 0; k < int(m_piece_info.size()); ++k) + else { - for (int j = 0; j < int(m_piece_info[k].size()); ++j) - { - TORRENT_ASSERT(int(m_piece_info[k][j]) != index - || (prio > 0 && prio == k && int(i->index) == j)); - } + TORRENT_ASSERT(prio == -1); + // make sure there's no entry + // with this index. (there shouldn't + // be since the priority is -1) + TORRENT_ASSERT(std::find(m_pieces.begin(), m_pieces.end(), index) + == m_pieces.end()); } -*/ + } + else if (m_sequential_download >= 0) + { + TORRENT_ASSERT(m_pieces.empty()); + TORRENT_ASSERT(m_priority_boundries.empty()); } int count = std::count_if(m_downloads.begin(), m_downloads.end() @@ -456,11 +430,21 @@ namespace libtorrent TORRENT_ASSERT(num_have == m_num_have); TORRENT_ASSERT(num_filtered == m_num_filtered); TORRENT_ASSERT(num_have_filtered == m_num_have_filtered); + + if (!m_dirty) + { + for (std::vector::const_iterator i = m_pieces.begin() + , end(m_pieces.end()); i != end; ++i) + { + TORRENT_ASSERT(m_piece_map[*i].priority(this) >= 0); + } + } } #endif float piece_picker::distributed_copies() const { + TORRENT_ASSERT(m_seeds >= 0); const float num_pieces = static_cast(m_piece_map.size()); int min_availability = piece_pos::max_peer_count; @@ -492,174 +476,257 @@ namespace libtorrent } } TORRENT_ASSERT(integer_part + fraction_part == num_pieces); - return float(min_availability) + (fraction_part / num_pieces); + return float(min_availability + m_seeds) + (fraction_part / num_pieces); + } + + void piece_picker::priority_range(int prio, int* start, int* end) + { + TORRENT_ASSERT(prio >= 0); + TORRENT_ASSERT(prio < int(m_priority_boundries.size()) + || m_dirty); + if (prio == 0) *start = 0; + else *start = m_priority_boundries[prio - 1]; + *end = m_priority_boundries[prio]; + TORRENT_ASSERT(*start <= *end); } void piece_picker::add(int index) { + TORRENT_ASSERT(!m_dirty); TORRENT_ASSERT(index >= 0); TORRENT_ASSERT(index < int(m_piece_map.size())); piece_pos& p = m_piece_map[index]; TORRENT_ASSERT(!p.filtered()); TORRENT_ASSERT(!p.have()); + TORRENT_ASSERT(m_sequential_download == -1); - int priority = p.priority(m_sequenced_download_threshold); - TORRENT_ASSERT(priority > 0); - if (int(m_piece_info.size()) <= priority) - m_piece_info.resize(priority + 1); + int priority = p.priority(this); + TORRENT_ASSERT(priority >= 0); + if (int(m_priority_boundries.size()) <= priority) + m_priority_boundries.resize(priority + 1, m_pieces.size()); - TORRENT_ASSERT(int(m_piece_info.size()) > priority); + TORRENT_ASSERT(int(m_priority_boundries.size()) >= priority); - if (is_ordered(priority)) + int range_start, range_end; + priority_range(priority, &range_start, &range_end); + int new_index; + if (range_end == range_start) new_index = range_start; + else new_index = rand() % (range_end - range_start) + range_start; + +#ifdef TORRENT_PICKER_LOG + std::cerr << "add " << index << " (" << priority << ")" << std::endl; + print_pieces(); +#endif + m_pieces.push_back(-1); + + for (;;) { - // the piece should be inserted ordered, not randomly - std::vector& v = m_piece_info[priority]; -// TORRENT_ASSERT(is_sorted(v.begin(), v.end()/*, std::greater()*/)); - std::vector::iterator i = std::lower_bound(v.begin(), v.end() - , index/*, std::greater()*/); - p.index = i - v.begin(); - v.insert(i, index); - i = v.begin() + p.index + 1; - for (;i != v.end(); ++i) + TORRENT_ASSERT(new_index < int(m_pieces.size())); + int temp = m_pieces[new_index]; + m_pieces[new_index] = index; + m_piece_map[index].index = new_index; + index = temp; + do { - ++m_piece_map[*i].index; - TORRENT_ASSERT(v[m_piece_map[*i].index] == *i); - } -// TORRENT_ASSERT(is_sorted(v.begin(), v.end()/*, std::greater()*/)); + temp = m_priority_boundries[priority]++; + ++priority; + } while (temp == new_index && priority < int(m_priority_boundries.size())); + new_index = temp; +#ifdef TORRENT_PICKER_LOG + print_pieces(); + std::cerr << " index: " << index + << " prio: " << priority + << " new_index: " << new_index + << std::endl; +#endif + if (priority >= int(m_priority_boundries.size())) break; + TORRENT_ASSERT(temp >= 0); } - else if (m_piece_info[priority].size() < 2) + if (index != -1) { - p.index = m_piece_info[priority].size(); - m_piece_info[priority].push_back(index); - } - else - { - // find a random position in the destination vector where we will place - // this entry. - int dst_index = rand() % m_piece_info[priority].size(); - - // copy the entry at that position to the back - m_piece_map[m_piece_info[priority][dst_index]].index - = m_piece_info[priority].size(); - m_piece_info[priority].push_back(m_piece_info[priority][dst_index]); + TORRENT_ASSERT(new_index == int(m_pieces.size() - 1)); + m_pieces[new_index] = index; + m_piece_map[index].index = new_index; - // and then replace the one at dst_index with the one we're moving. - // this procedure is to make sure there's no ordering when pieces - // are moved in sequenced order. - p.index = dst_index; - m_piece_info[priority][p.index] = index; +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif } } - // will update the piece with the given properties (priority, elem_index) - // to place it at the correct position in the vectors. - void piece_picker::move(int priority, int elem_index) + void piece_picker::remove(int priority, int elem_index) { - TORRENT_ASSERT(priority > 0); + TORRENT_ASSERT(!m_dirty); + TORRENT_ASSERT(priority >= 0); + TORRENT_ASSERT(m_sequential_download == -1); + +#ifdef TORRENT_PICKER_LOG + std::cerr << "remove " << m_pieces[elem_index] << " (" << priority << ")" << std::endl; +#endif + int next_index = elem_index; + TORRENT_ASSERT(m_piece_map[m_pieces[elem_index]].priority(this) == -1); + for (;;) + { +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + TORRENT_ASSERT(elem_index < int(m_pieces.size())); + int temp; + do + { + temp = --m_priority_boundries[priority]; + ++priority; + } while (next_index == temp && priority < int(m_priority_boundries.size())); + if (next_index == temp) break; + next_index = temp; + + int piece = m_pieces[next_index]; + m_pieces[elem_index] = piece; + m_piece_map[piece].index = elem_index; + TORRENT_ASSERT(m_piece_map[piece].priority(this) == priority - 1); + TORRENT_ASSERT(elem_index < int(m_pieces.size() - 1)); + elem_index = next_index; + + if (priority == int(m_priority_boundries.size())) + break; + } + m_pieces.pop_back(); + TORRENT_ASSERT(next_index == int(m_pieces.size())); +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + } + + // will update the piece with the given properties (priority, elem_index) + // to place it at the correct position + void piece_picker::update(int priority, int elem_index) + { + TORRENT_ASSERT(!m_dirty); + TORRENT_ASSERT(priority >= 0); TORRENT_ASSERT(elem_index >= 0); - TORRENT_ASSERT(m_files_checked_called); + TORRENT_ASSERT(m_sequential_download == -1); - TORRENT_ASSERT(int(m_piece_info.size()) > priority); - TORRENT_ASSERT(int(m_piece_info[priority].size()) > elem_index); + TORRENT_ASSERT(int(m_priority_boundries.size()) > priority); - int index = m_piece_info[priority][elem_index]; + int index = m_pieces[elem_index]; // update the piece_map piece_pos& p = m_piece_map[index]; TORRENT_ASSERT(int(p.index) == elem_index || p.have()); - int new_priority = p.priority(m_sequenced_download_threshold); + int new_priority = p.priority(this); if (new_priority == priority) return; - if (int(m_piece_info.size()) <= new_priority - && new_priority > 0) + if (new_priority == -1) { - m_piece_info.resize(new_priority + 1); - TORRENT_ASSERT(int(m_piece_info.size()) > new_priority); + remove(priority, elem_index); + return; } - if (new_priority == 0) + if (int(m_priority_boundries.size()) <= new_priority) + m_priority_boundries.resize(new_priority + 1, m_pieces.size()); + +#ifdef TORRENT_PICKER_LOG + std::cerr << "update " << index << " (" << priority << "->" << new_priority << ")" << std::endl; +#endif + if (priority > new_priority) { - // this means the piece should not have an entry - } - else if (is_ordered(new_priority)) - { - // the piece should be inserted ordered, not randomly - std::vector& v = m_piece_info[new_priority]; -// TORRENT_ASSERT(is_sorted(v.begin(), v.end()/*, std::greater()*/)); - std::vector::iterator i = std::lower_bound(v.begin(), v.end() - , index/*, std::greater()*/); - p.index = i - v.begin(); - v.insert(i, index); - i = v.begin() + p.index + 1; - for (;i != v.end(); ++i) + int new_index; + int temp = index; + for (;;) { - ++m_piece_map[*i].index; - TORRENT_ASSERT(v[m_piece_map[*i].index] == *i); +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + --priority; + new_index = m_priority_boundries[priority]++; + TORRENT_ASSERT(new_index < int(m_pieces.size())); + if (temp != m_pieces[new_index]) + { + temp = m_pieces[new_index]; + m_pieces[elem_index] = temp; + m_piece_map[temp].index = elem_index; + TORRENT_ASSERT(elem_index < int(m_pieces.size())); + } + elem_index = new_index; + if (priority == new_priority) break; } -// TORRENT_ASSERT(is_sorted(v.begin(), v.end()/*, std::greater()*/)); - } - else if (m_piece_info[new_priority].size() < 2) - { - p.index = m_piece_info[new_priority].size(); - m_piece_info[new_priority].push_back(index); +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + m_pieces[elem_index] = index; + m_piece_map[index].index = elem_index; + TORRENT_ASSERT(elem_index < int(m_pieces.size())); +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + shuffle(priority, elem_index); +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + TORRENT_ASSERT(m_piece_map[index].priority(this) == priority); } else { - // find a random position in the destination vector where we will place - // this entry. - int dst_index = rand() % m_piece_info[new_priority].size(); - - // copy the entry at that position to the back - m_piece_map[m_piece_info[new_priority][dst_index]].index - = m_piece_info[new_priority].size(); - m_piece_info[new_priority].push_back(m_piece_info[new_priority][dst_index]); - - // and then replace the one at dst_index with the one we're moving. - // this procedure is to make sure there's no ordering when pieces - // are moved in sequenced order. - p.index = dst_index; - m_piece_info[new_priority][p.index] = index; - } - TORRENT_ASSERT(new_priority == 0 || p.index < m_piece_info[p.priority(m_sequenced_download_threshold)].size()); - TORRENT_ASSERT(new_priority == 0 || m_piece_info[p.priority(m_sequenced_download_threshold)][p.index] == index); - - if (is_ordered(priority)) - { - // remove the element from the source vector and preserve the order - std::vector& v = m_piece_info[priority]; - v.erase(v.begin() + elem_index); - for (std::vector::iterator i = v.begin() + elem_index; - i != v.end(); ++i) + int new_index; + int temp = index; + for (;;) { - --m_piece_map[*i].index; - TORRENT_ASSERT(v[m_piece_map[*i].index] == *i); +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + new_index = --m_priority_boundries[priority]; + TORRENT_ASSERT(new_index < int(m_pieces.size())); + if (temp != m_pieces[new_index]) + { + temp = m_pieces[new_index]; + m_pieces[elem_index] = temp; + m_piece_map[temp].index = elem_index; + TORRENT_ASSERT(elem_index < int(m_pieces.size())); + } + elem_index = new_index; + ++priority; + if (priority == new_priority) break; } +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + m_pieces[elem_index] = index; + m_piece_map[index].index = elem_index; + TORRENT_ASSERT(elem_index < int(m_pieces.size())); +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + shuffle(priority, elem_index); +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + TORRENT_ASSERT(m_piece_map[index].priority(this) == priority); } - else - { - // this will remove elem from the source vector without - // preserving order, but the order is random anyway - int replace_index = m_piece_info[priority][elem_index] = m_piece_info[priority].back(); - if (index != replace_index) - { - // update the entry we moved from the back - m_piece_map[replace_index].index = elem_index; + } - TORRENT_ASSERT(int(m_piece_info[priority].size()) > elem_index); - // this may not necessarily be the case. If we've just updated the threshold and are updating - // the piece map -// TORRENT_ASSERT((int)m_piece_map[replace_index].priority(m_sequenced_download_threshold) == priority); - TORRENT_ASSERT(int(m_piece_map[replace_index].index) == elem_index); - TORRENT_ASSERT(m_piece_info[priority][elem_index] == replace_index); - } - else - { - TORRENT_ASSERT(int(m_piece_info[priority].size()) == elem_index+1); - } + void piece_picker::shuffle(int priority, int elem_index) + { + TORRENT_ASSERT(!m_dirty); + TORRENT_ASSERT(priority >= 0); + TORRENT_ASSERT(elem_index >= 0); + TORRENT_ASSERT(m_sequential_download == -1); + + int range_start, range_end; + priority_range(priority, &range_start, &range_end); + TORRENT_ASSERT(range_start < range_end); + int other_index = rand() % (range_end - range_start) + range_start; - m_piece_info[priority].pop_back(); - } + if (other_index == elem_index) return; + + // swap other_index with elem_index + piece_pos& p1 = m_piece_map[m_pieces[other_index]]; + piece_pos& p2 = m_piece_map[m_pieces[elem_index]]; + + int temp = p1.index; + p1.index = p2.index; + p2.index = temp; + std::swap(m_pieces[other_index], m_pieces[elem_index]); } void piece_picker::sort_piece(std::vector::iterator dp) @@ -684,280 +751,261 @@ namespace libtorrent TORRENT_ASSERT(index >= 0); TORRENT_ASSERT(index < (int)m_piece_map.size()); - TORRENT_ASSERT(m_files_checked_called); TORRENT_ASSERT(m_piece_map[index].downloading == 1); std::vector::iterator i - = std::find_if(m_downloads.begin(), - m_downloads.end(), - has_index(index)); + = std::find_if(m_downloads.begin(), m_downloads.end() + , has_index(index)); + TORRENT_ASSERT(i != m_downloads.end()); erase_download_piece(i); piece_pos& p = m_piece_map[index]; - int prev_priority = p.priority(m_sequenced_download_threshold); + int prev_priority = p.priority(this); p.downloading = 0; - int new_priority = p.priority(m_sequenced_download_threshold); + int new_priority = p.priority(this); if (new_priority == prev_priority) return; - - if (prev_priority == 0) + if (m_dirty) return; + if (m_sequential_download >= 0) + { + m_dirty = true; + return; + } + if (prev_priority == -1) { add(index); } else { - move(prev_priority, p.index); + update(prev_priority, p.index); } } void piece_picker::inc_refcount_all() { TORRENT_PIECE_PICKER_INVARIANT_CHECK; - TORRENT_ASSERT(m_files_checked_called); - - // in general priority = availability * 2 - // see piece_block::priority() - - // this will insert two empty vectors at the start of the - // piece_info vector. It is done like this as an optimization, - // to swap vectors instead of copying them - while (m_piece_info.size() < 3 - || (!m_piece_info.rbegin()->empty()) - || (!(m_piece_info.rbegin()+1)->empty())) + ++m_seeds; + if (m_seeds == 1) { - m_piece_info.push_back(std::vector()); - } - TORRENT_ASSERT(m_piece_info.rbegin()->empty()); - TORRENT_ASSERT((m_piece_info.rbegin()+1)->empty()); - typedef std::vector > piece_info_t; - for (piece_info_t::reverse_iterator i = m_piece_info.rbegin(), j(i+1) - , k(j+1), end(m_piece_info.rend()); k != end; ++i, ++j, ++k) - { - k->swap(*i); - } - TORRENT_ASSERT(m_piece_info.begin()->empty()); - TORRENT_ASSERT((m_piece_info.begin()+1)->empty()); - - // if we have some priorities that are clamped to the - // sequenced download, move that vector back down - int last_index = m_piece_info.size() - 1; - int cap_index = m_sequenced_download_threshold * 2; - if (last_index == cap_index) - { - // this is the case when the top bucket - // was moved up into the sequenced download bucket. - m_piece_info.push_back(std::vector()); - m_piece_info[cap_index].swap(m_piece_info[cap_index+1]); - ++last_index; - } - else if (last_index > cap_index) - { - if (last_index - cap_index == 1) - { - m_piece_info.push_back(std::vector()); - ++last_index; - } - m_piece_info[cap_index+1].swap(m_piece_info[cap_index+2]); - m_piece_info[cap_index].swap(m_piece_info[cap_index+1]); - } - - // now, increase the peer count of all the pieces. - // because of different priorities, some pieces may have - // ended up in the wrong priority bucket. Adjust that. - for (std::vector::iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i) - { - int prev_prio = i->priority(m_sequenced_download_threshold); - TORRENT_ASSERT(prev_prio < int(m_piece_info.size())); - ++i->peer_count; - // if the assumption that the priority would - // increase by 2 when increasing the availability - // by one isn't true for this particular piece, correct it. - // that assumption is true for all pieces with priority 0 or 1 - int new_prio = i->priority(m_sequenced_download_threshold); - TORRENT_ASSERT(new_prio <= cap_index); - if (prev_prio == 0 && new_prio > 0) - { - add(i - m_piece_map.begin()); - continue; - } - if (new_prio == 0) - { - TORRENT_ASSERT(prev_prio == 0); - continue; - } - if (prev_prio == cap_index) - { - TORRENT_ASSERT(new_prio == cap_index); - continue; - } - if (new_prio == prev_prio + 2 && new_prio != cap_index) - { - TORRENT_ASSERT(new_prio != cap_index); - continue; - } - if (prev_prio + 2 >= cap_index) - { - // these two vectors will have moved one extra step - // passed the sequenced download threshold - ++prev_prio; - } - TORRENT_ASSERT(prev_prio + 2 != cap_index); - TORRENT_ASSERT(prev_prio + 2 != new_prio); - move(prev_prio + 2, i->index); + // when m_seeds is increased from 0 to 1 + // we may have to add pieces that previously + // didn't have any peers + m_dirty = true; } } void piece_picker::dec_refcount_all() { TORRENT_PIECE_PICKER_INVARIANT_CHECK; - TORRENT_ASSERT(m_files_checked_called); - TORRENT_ASSERT(m_piece_info.size() >= 2); - TORRENT_ASSERT(m_piece_info.front().empty()); - // swap all vectors two steps down - if (m_piece_info.size() > 2) - { - typedef std::vector > piece_info_t; - for (piece_info_t::iterator i = m_piece_info.begin(), j(i+1) - , k(j+1), end(m_piece_info.end()); k != end; ++i, ++j, ++k) - { - k->swap(*i); - } - } - else - { - m_piece_info.resize(3); - } - int last_index = m_piece_info.size() - 1; - if ((m_piece_info.size() & 1) == 0) - { - // if there's an even number of vectors, swap - // the last two to get the same layout in both cases - m_piece_info[last_index].swap(m_piece_info[last_index-1]); - } - TORRENT_ASSERT(m_piece_info.back().empty()); - int pushed_out_index = m_piece_info.size() - 2; - int cap_index = m_sequenced_download_threshold * 2; - TORRENT_ASSERT(m_piece_info[last_index].empty()); - if (last_index >= cap_index) + if (m_seeds > 0) { - TORRENT_ASSERT(pushed_out_index == cap_index - 1 - || m_piece_info[cap_index - 1].empty()); - m_piece_info[cap_index].swap(m_piece_info[cap_index - 2]); - if (cap_index == pushed_out_index) - pushed_out_index = cap_index - 2; + --m_seeds; + if (m_seeds == 0) + { + // when m_seeds is decreased from 1 to 0 + // we may have to remove pieces that previously + // didn't have any peers + m_dirty = true; + } + return; } - - // first is the vector that were - // bumped down to 0. The should always be moved - // since they have to be removed or reinserted - std::vector().swap(m_piece_info.front()); + TORRENT_ASSERT(m_seeds == 0); for (std::vector::iterator i = m_piece_map.begin() , end(m_piece_map.end()); i != end; ++i) { - int prev_prio = i->priority(m_sequenced_download_threshold); - TORRENT_ASSERT(prev_prio < int(m_piece_info.size())); - TORRENT_ASSERT(pushed_out_index < int(m_piece_info.size())); TORRENT_ASSERT(i->peer_count > 0); --i->peer_count; - // if the assumption that the priority would - // decrease by 2 when decreasing the availability - // by one isn't true for this particular piece, correct it. - // that assumption is true for all pieces with priority 0 or 1 - if (prev_prio == 0) - { - TORRENT_ASSERT(i->priority(m_sequenced_download_threshold) == 0); - continue; - } - - int new_prio = i->priority(m_sequenced_download_threshold); - if (prev_prio == cap_index) - { - if (new_prio == cap_index) continue; - prev_prio += 2; - } - else if (new_prio == prev_prio - 2) - { - continue; - } - else if (prev_prio == 2) - { - // if this piece was pushed down to priority 0, it was - // removed - TORRENT_ASSERT(new_prio > 0); - add(i - m_piece_map.begin()); - continue; - } - else if (prev_prio == 1) - { - // if this piece was one of the vectors that was pushed to the - // top, adjust the prev_prio to point to that vector, so that - // the pieces are moved from there - prev_prio = pushed_out_index + 2; - } - move(prev_prio - 2, i->index); } + + m_dirty = true; } - void piece_picker::inc_refcount(int i) + void piece_picker::inc_refcount(int index) { -// TORRENT_PIECE_PICKER_INVARIANT_CHECK; - TORRENT_ASSERT(i >= 0); - TORRENT_ASSERT(i < (int)m_piece_map.size()); - TORRENT_ASSERT(m_files_checked_called); + TORRENT_PIECE_PICKER_INVARIANT_CHECK; - piece_pos& p = m_piece_map[i]; - int index = p.index; - int prev_priority = p.priority(m_sequenced_download_threshold); - TORRENT_ASSERT(prev_priority < int(m_piece_info.size())); - - TORRENT_ASSERT(p.peer_count < piece_pos::max_peer_count); - p.peer_count++; - TORRENT_ASSERT(p.peer_count != 0); - - // if we have the piece or if it's filtered - // we don't have to move any entries in the piece_info vector - if (p.priority(m_sequenced_download_threshold) == prev_priority) return; - - if (prev_priority == 0) + piece_pos& p = m_piece_map[index]; + if (m_sequential_download >= 0) { - add(i); + ++p.peer_count; + m_dirty = true; + return; } + + int prev_priority = p.priority(this); + ++p.peer_count; + if (m_dirty) return; + int new_priority = p.priority(this); + if (prev_priority == new_priority) return; + if (prev_priority == -1) + add(index); else + update(prev_priority, p.index); + } + + void piece_picker::dec_refcount(int index) + { + TORRENT_PIECE_PICKER_INVARIANT_CHECK; + + piece_pos& p = m_piece_map[index]; + if (m_sequential_download >= 0) { - move(prev_priority, index); + TORRENT_ASSERT(p.peer_count > 0); + --p.peer_count; + m_dirty = true; + return; } + int prev_priority = p.priority(this); + TORRENT_ASSERT(p.peer_count > 0); + --p.peer_count; + if (m_dirty) return; + if (prev_priority >= 0) update(prev_priority, p.index); + } + + void piece_picker::inc_refcount(bitfield const& bitmask) + { + TORRENT_PIECE_PICKER_INVARIANT_CHECK; + TORRENT_ASSERT(bitmask.size() == m_piece_map.size()); + + int index = 0; + bool updated = false; + for (bitfield::const_iterator i = bitmask.begin() + , end(bitmask.end()); i != end; ++i, ++index) + { + if (*i) + { + ++m_piece_map[index].peer_count; + updated = true; + } + } + + if (updated && m_sequential_download == -1) m_dirty = true; + } + + void piece_picker::dec_refcount(bitfield const& bitmask) + { + TORRENT_PIECE_PICKER_INVARIANT_CHECK; + TORRENT_ASSERT(bitmask.size() == m_piece_map.size()); + + int index = 0; + bool updated = false; + for (bitfield::const_iterator i = bitmask.begin() + , end(bitmask.end()); i != end; ++i, ++index) + { + if (*i) + { + --m_piece_map[index].peer_count; + updated = true; + } + } + + if (updated && m_sequential_download == -1) m_dirty = true; + } + + void piece_picker::update_pieces() const + { + TORRENT_ASSERT(m_dirty); + TORRENT_ASSERT(m_sequential_download == -1); + if (m_priority_boundries.empty()) m_priority_boundries.resize(1, 0); +#ifdef TORRENT_PICKER_LOG + std::cerr << "update_pieces" << std::endl; +#endif + std::fill(m_priority_boundries.begin(), m_priority_boundries.end(), 0); + for (std::vector::iterator i = m_piece_map.begin() + , end(m_piece_map.end()); i != end; ++i) + { + int prio = i->priority(this); + if (prio == -1) continue; + if (prio >= int(m_priority_boundries.size())) + m_priority_boundries.resize(prio + 1, 0); + i->index = m_priority_boundries[prio]; + ++m_priority_boundries[prio]; + } + +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + + int index = 0; + for (std::vector::iterator i = m_priority_boundries.begin() + , end(m_priority_boundries.end()); i != end; ++i) + { + *i += index; + index = *i; + } + m_pieces.resize(index, 0); + +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif + + index = 0; + for (std::vector::iterator i = m_piece_map.begin() + , end(m_piece_map.end()); i != end; ++i, ++index) + { + piece_pos& p = *i; + int prio = p.priority(this); + if (prio == -1) continue; + int new_index = (prio == 0 ? 0 : m_priority_boundries[prio - 1]) + p.index; + m_pieces[new_index] = index; + } + + int start = 0; + for (std::vector::iterator i = m_priority_boundries.begin() + , end(m_priority_boundries.end()); i != end; ++i) + { + if (start == *i) continue; + std::random_shuffle(&m_pieces[0] + start, &m_pieces[0] + *i); + start = *i; + } + + index = 0; + for (std::vector::const_iterator i = m_pieces.begin() + , end(m_pieces.end()); i != end; ++i, ++index) + { + TORRENT_ASSERT(*i >= 0 && *i < int(m_piece_map.size())); + m_piece_map[*i].index = index; + } + + m_dirty = false; +#ifdef TORRENT_PICKER_LOG + print_pieces(); +#endif #ifndef NDEBUG -// integrity_check(); + check_invariant(); #endif - return; } - void piece_picker::dec_refcount(int i) + void piece_picker::we_dont_have(int index) { -// TORRENT_PIECE_PICKER_INVARIANT_CHECK; + TORRENT_PIECE_PICKER_INVARIANT_CHECK; + TORRENT_ASSERT(index >= 0); + TORRENT_ASSERT(index < (int)m_piece_map.size()); - TORRENT_ASSERT(m_files_checked_called); - TORRENT_ASSERT(i >= 0); - TORRENT_ASSERT(i < (int)m_piece_map.size()); + piece_pos& p = m_piece_map[index]; + TORRENT_ASSERT(p.downloading == 0); - piece_pos& p = m_piece_map[i]; - int prev_priority = p.priority(m_sequenced_download_threshold); - TORRENT_ASSERT(prev_priority < int(m_piece_info.size())); - int index = p.index; - TORRENT_ASSERT(p.peer_count > 0); + if (!p.have()) return; - if (p.peer_count > 0) - p.peer_count--; + if (m_sequential_download > index) + m_sequential_download = index; - if (p.priority(m_sequenced_download_threshold) == prev_priority) return; + if (p.filtered()) + { + ++m_num_filtered; + --m_num_have_filtered; + } - move(prev_priority, index); + --m_num_have; + p.set_not_have(); + + if (m_dirty) return; + if (p.priority(this) >= 0) add(index); } // this is used to indicate that we succesfully have @@ -972,8 +1020,8 @@ namespace libtorrent piece_pos& p = m_piece_map[index]; int info_index = p.index; - int priority = p.priority(m_sequenced_download_threshold); - TORRENT_ASSERT(priority < int(m_piece_info.size())); + int priority = p.priority(this); + TORRENT_ASSERT(priority < int(m_priority_boundries.size())); if (p.downloading) { @@ -989,6 +1037,13 @@ namespace libtorrent TORRENT_ASSERT(std::find_if(m_downloads.begin(), m_downloads.end() , has_index(index)) == m_downloads.end()); + if (m_sequential_download == index) + { + ++m_sequential_download; + for (std::vector::const_iterator i = m_piece_map.begin() + m_sequential_download + , end(m_piece_map.end()); i != end && (i->have() || i->filtered()); + ++i, ++m_sequential_download); + } if (p.have()) return; if (p.filtered()) { @@ -997,12 +1052,12 @@ namespace libtorrent } ++m_num_have; p.set_have(); - if (priority == 0) return; - TORRENT_ASSERT(p.priority(m_sequenced_download_threshold) == 0); - move(priority, info_index); + if (priority == -1) return; + if (m_dirty) return; + remove(priority, info_index); + TORRENT_ASSERT(p.priority(this) == -1); } - bool piece_picker::set_piece_priority(int index, int new_piece_priority) { TORRENT_PIECE_PICKER_INVARIANT_CHECK; @@ -1016,8 +1071,8 @@ namespace libtorrent // if the priority isn't changed, don't do anything if (new_piece_priority == int(p.piece_priority)) return false; - int prev_priority = p.priority(m_sequenced_download_threshold); - TORRENT_ASSERT(prev_priority < int(m_piece_info.size())); + int prev_priority = p.priority(this); + TORRENT_ASSERT(prev_priority < int(m_priority_boundries.size())); bool ret = false; if (new_piece_priority == piece_pos::filter_priority @@ -1040,18 +1095,20 @@ namespace libtorrent TORRENT_ASSERT(m_num_have_filtered >= 0); p.piece_priority = new_piece_priority; - int new_priority = p.priority(m_sequenced_download_threshold); - TORRENT_ASSERT(prev_priority < int(m_piece_info.size())); + int new_priority = p.priority(this); - if (new_priority == prev_priority) return false; - - if (prev_priority == 0) + if (prev_priority == new_priority) return false; + + TORRENT_ASSERT(prev_priority < int(m_priority_boundries.size())); + + if (m_dirty) return ret; + if (prev_priority == -1) { add(index); } else { - move(prev_priority, p.index); + update(prev_priority, p.index); } return ret; } @@ -1105,7 +1162,7 @@ namespace libtorrent // to pick blocks from the same pieces as fast peers, and vice // versa. Downloading pieces are marked as being fast, medium // or slow once they're started. - void piece_picker::pick_pieces(const std::vector& pieces + void piece_picker::pick_pieces(bitfield const& pieces , std::vector& interesting_blocks , int num_blocks, int prefer_whole_pieces , void* peer, piece_state_t speed, bool rarest_first @@ -1114,9 +1171,10 @@ namespace libtorrent TORRENT_PIECE_PICKER_INVARIANT_CHECK; TORRENT_ASSERT(num_blocks > 0); TORRENT_ASSERT(pieces.size() == m_piece_map.size()); - TORRENT_ASSERT(m_files_checked_called); - TORRENT_ASSERT(m_piece_info.begin() != m_piece_info.end()); + TORRENT_ASSERT(!m_priority_boundries.empty() + || m_sequential_download >= 0 + || m_dirty); // this will be filled with blocks that we should not request // unless we can't find num_blocks among the other ones. @@ -1125,8 +1183,6 @@ namespace libtorrent // blocks belonging to a piece that others have // downloaded to std::vector backup_blocks; - // suggested pieces for each vector is put in this vector - std::vector suggested_bucket; const std::vector empty_vector; // When prefer_whole_pieces is set (usually set when downloading from @@ -1140,50 +1196,38 @@ namespace libtorrent if (num_blocks <= 0) return; - if (rarest_first) + if (!suggested_pieces.empty()) { - // this loop will loop from pieces with priority 1 and up - // until we either reach the end of the piece list or - // has filled the interesting_blocks with num_blocks - // blocks. + num_blocks = add_blocks(suggested_pieces, pieces + , interesting_blocks, num_blocks + , prefer_whole_pieces, peer, empty_vector); + if (num_blocks == 0) return; + } - // +1 is to ignore pieces that no peer has. The bucket with index 0 contains - // pieces that 0 other peers have. bucket will point to a bucket with - // pieces with the same priority. It will be iterated in priority - // order (high priority/rare pices first). The content of each - // bucket is randomized - for (std::vector >::const_iterator bucket - = m_piece_info.begin() + 1; num_blocks > 0 && bucket != m_piece_info.end(); - ++bucket) + if (m_sequential_download >= 0) + { + for (int i = m_sequential_download; + i < int(m_piece_map.size()) && num_blocks > 0; ++i) { - if (bucket->empty()) continue; - if (!suggested_pieces.empty()) + if (!can_pick(i, pieces)) continue; + int num_blocks_in_piece = blocks_in_piece(i); + if (prefer_whole_pieces == 0 && num_blocks_in_piece > num_blocks) + num_blocks_in_piece = num_blocks; + for (int j = 0; j < num_blocks_in_piece; ++j) { - int bucket_index = bucket - m_piece_info.begin(); - suggested_bucket.clear(); - for (std::vector::const_iterator i = suggested_pieces.begin() - , end(suggested_pieces.end()); i != end; ++i) - { - TORRENT_ASSERT(*i >= 0); - TORRENT_ASSERT(*i < int(m_piece_map.size())); - if (!can_pick(*i, pieces)) continue; - if (m_piece_map[*i].priority(m_sequenced_download_threshold) == bucket_index) - suggested_bucket.push_back(*i); - } - if (!suggested_bucket.empty()) - { - num_blocks = add_blocks(suggested_bucket, pieces - , interesting_blocks, num_blocks - , prefer_whole_pieces, peer, empty_vector); - if (num_blocks == 0) break; - } + interesting_blocks.push_back(piece_block(i, j)); + --num_blocks; } - num_blocks = add_blocks(*bucket, pieces - , interesting_blocks, num_blocks - , prefer_whole_pieces, peer, suggested_bucket); - TORRENT_ASSERT(num_blocks >= 0); } } + else if (rarest_first) + { + if (m_dirty) update_pieces(); + num_blocks = add_blocks(m_pieces, pieces + , interesting_blocks, num_blocks + , prefer_whole_pieces, peer, suggested_pieces); + TORRENT_ASSERT(num_blocks >= 0); + } else { // we're not using rarest first (only for the first @@ -1215,7 +1259,7 @@ namespace libtorrent for (int k = start; k < end; ++k) { TORRENT_ASSERT(m_piece_map[piece].downloading == false); - TORRENT_ASSERT(m_piece_map[k].priority(m_sequenced_download_threshold) > 0); + TORRENT_ASSERT(m_piece_map[k].priority(this) >= 0); int num_blocks_in_piece = blocks_in_piece(k); if (prefer_whole_pieces == 0 && num_blocks_in_piece > num_blocks) num_blocks_in_piece = num_blocks; @@ -1240,7 +1284,7 @@ namespace libtorrent , backup_blocks.begin(), backup_blocks.end()); } - bool piece_picker::can_pick(int piece, std::vector const& bitmask) const + bool piece_picker::can_pick(int piece, bitfield const& bitmask) const { TORRENT_ASSERT(piece >= 0 && piece < int(m_piece_map.size())); return bitmask[piece] @@ -1287,7 +1331,7 @@ namespace libtorrent } int piece_picker::add_blocks(std::vector const& piece_list - , std::vector const& pieces + , bitfield const& pieces , std::vector& interesting_blocks , int num_blocks, int prefer_whole_pieces , void* peer, std::vector const& ignore) const @@ -1299,19 +1343,17 @@ namespace libtorrent TORRENT_ASSERT(*i < (int)m_piece_map.size()); // if the peer doesn't have the piece + // or if it's set to 0 priority // skip it - if (!pieces[*i]) continue; + if (!can_pick(*i, pieces)) continue; // ignore pieces found in the ignore list if (std::find(ignore.begin(), ignore.end(), *i) != ignore.end()) continue; - // skip the piece is the priority is 0 - TORRENT_ASSERT(m_piece_map[*i].priority(m_sequenced_download_threshold) > 0); - - int num_blocks_in_piece = blocks_in_piece(*i); - + TORRENT_ASSERT(m_piece_map[*i].priority(this) >= 0); TORRENT_ASSERT(m_piece_map[*i].downloading == 0); - TORRENT_ASSERT(m_piece_map[*i].priority(m_sequenced_download_threshold) > 0); + + int num_blocks_in_piece = blocks_in_piece(*i); // pick a new piece if (prefer_whole_pieces == 0) @@ -1328,7 +1370,7 @@ namespace libtorrent boost::tie(start, end) = expand_piece(*i, prefer_whole_pieces, pieces); for (int k = start; k < end; ++k) { - TORRENT_ASSERT(m_piece_map[k].priority(m_sequenced_download_threshold) > 0); + TORRENT_ASSERT(m_piece_map[k].priority(this) > 0); num_blocks_in_piece = blocks_in_piece(k); for (int j = 0; j < num_blocks_in_piece; ++j) { @@ -1351,7 +1393,7 @@ namespace libtorrent return num_blocks; } - int piece_picker::add_blocks_downloading(std::vector const& pieces + int piece_picker::add_blocks_downloading(bitfield const& pieces , std::vector& interesting_blocks , std::vector& backup_blocks , int num_blocks, int prefer_whole_pieces @@ -1543,7 +1585,7 @@ namespace libtorrent } std::pair piece_picker::expand_piece(int piece, int whole_pieces - , std::vector const& have) const + , bitfield const& have) const { if (whole_pieces == 0) return std::make_pair(piece, piece + 1); @@ -1639,12 +1681,9 @@ namespace libtorrent return i->info[block.block_index].state == block_info::state_finished; } - bool piece_picker::mark_as_downloading(piece_block block , void* peer, piece_state_t state) { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - TORRENT_ASSERT(block.piece_index >= 0); TORRENT_ASSERT(block.block_index >= 0); TORRENT_ASSERT(block.piece_index < (int)m_piece_map.size()); @@ -1654,11 +1693,14 @@ namespace libtorrent piece_pos& p = m_piece_map[block.piece_index]; if (p.downloading == 0) { - int prio = p.priority(m_sequenced_download_threshold); - TORRENT_ASSERT(prio < int(m_piece_info.size())); + TORRENT_PIECE_PICKER_INVARIANT_CHECK; + int prio = p.priority(this); + TORRENT_ASSERT(prio < int(m_priority_boundries.size()) + || m_sequential_download >= 0 + || m_dirty); TORRENT_ASSERT(prio > 0); p.downloading = 1; - move(prio, p.index); + if (prio >= 0 && m_sequential_download == -1 && !m_dirty) update(prio, p.index); downloading_piece& dp = add_download_piece(); dp.state = state; @@ -1671,6 +1713,7 @@ namespace libtorrent } else { + TORRENT_PIECE_PICKER_INVARIANT_CHECK; std::vector::iterator i = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); TORRENT_ASSERT(i != m_downloads.end()); @@ -1713,13 +1756,14 @@ namespace libtorrent void piece_picker::get_availability(std::vector& avail) const { + TORRENT_ASSERT(m_seeds >= 0); TORRENT_PIECE_PICKER_INVARIANT_CHECK; avail.resize(m_piece_map.size()); std::vector::iterator j = avail.begin(); for (std::vector::const_iterator i = m_piece_map.begin() , end(m_piece_map.end()); i != end; ++i, ++j) - *j = i->peer_count; + *j = i->peer_count + m_seeds; } void piece_picker::mark_as_writing(piece_block block, void* peer) @@ -1731,10 +1775,6 @@ namespace libtorrent TORRENT_ASSERT(block.piece_index < (int)m_piece_map.size()); TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index)); - // this might be the case if a piece fails, is restored, and then - // completed from a different peer (from which the piece was requested - // before it failed the hash check) - TORRENT_ASSERT(m_piece_map[block.piece_index].downloading); std::vector::iterator i @@ -1749,7 +1789,8 @@ namespace libtorrent TORRENT_ASSERT(info.state != block_info::state_writing); ++i->writing; info.state = block_info::state_writing; - if (info.num_peers > 0) --info.num_peers; + TORRENT_ASSERT(info.num_peers > 0); + info.num_peers = 0; if (i->requested == 0) { @@ -1759,6 +1800,31 @@ namespace libtorrent } sort_piece(i); } + + void piece_picker::write_failed(piece_block block) + { + TORRENT_PIECE_PICKER_INVARIANT_CHECK; + + std::vector::iterator i + = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); + TORRENT_ASSERT(i != m_downloads.end()); + block_info& info = i->info[block.block_index]; + TORRENT_ASSERT(info.state == block_info::state_writing); + + --i->writing; + if (info.num_peers > 0) + { + // there are other peers on this block + // turn it back into requested + ++i->requested; + info.state = block_info::state_requested; + } + else + { + info.state = block_info::state_none; + } + info.peer = 0; + } void piece_picker::mark_as_finished(piece_block block, void* peer) { @@ -1774,11 +1840,11 @@ namespace libtorrent TORRENT_PIECE_PICKER_INVARIANT_CHECK; TORRENT_ASSERT(peer == 0); - int prio = p.priority(m_sequenced_download_threshold); - TORRENT_ASSERT(prio < int(m_piece_info.size())); + int prio = p.priority(this); + TORRENT_ASSERT(prio < int(m_priority_boundries.size()) + || m_dirty); p.downloading = 1; - if (prio > 0) move(prio, p.index); - else TORRENT_ASSERT(p.priority(m_sequenced_download_threshold) == 0); + if (prio >= 0 && !m_dirty) update(prio, p.index); downloading_piece& dp = add_download_piece(); dp.state = none; @@ -1786,6 +1852,7 @@ namespace libtorrent block_info& info = dp.info[block.block_index]; info.peer = peer; TORRENT_ASSERT(info.state == block_info::state_none); + TORRENT_ASSERT(info.num_peers == 0); if (info.state != block_info::state_finished) { ++dp.finished; @@ -1801,6 +1868,7 @@ namespace libtorrent = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); TORRENT_ASSERT(i != m_downloads.end()); block_info& info = i->info[block.block_index]; + TORRENT_ASSERT(info.num_peers == 0); info.peer = peer; TORRENT_ASSERT(info.state == block_info::state_writing || peer == 0); @@ -1850,6 +1918,8 @@ namespace libtorrent return i->info[block.block_index].peer; } + // this is called when a request is rejected or when + // a peer disconnects. The piece might be in any state void piece_picker::abort_download(piece_block block) { TORRENT_PIECE_PICKER_INVARIANT_CHECK; @@ -1871,37 +1941,40 @@ namespace libtorrent TORRENT_ASSERT(i != m_downloads.end()); block_info& info = i->info[block.block_index]; - --info.num_peers; - if (info.num_peers > 0) return; - if (i->info[block.block_index].state == block_info::state_finished - || i->info[block.block_index].state == block_info::state_writing) - { + if (i->info[block.block_index].state != block_info::state_requested) return; - } + + if (info.num_peers > 0) --info.num_peers; TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index)); - TORRENT_ASSERT(i->info[block.block_index].state == block_info::state_requested); + + // if there are other peers, leave the block requested + if (info.num_peers > 0) return; + + // clear the downloader of this block + info.peer = 0; // clear this block as being downloaded info.state = block_info::state_none; --i->requested; - // clear the downloader of this block - info.peer = 0; - // if there are no other blocks in this piece // that's being downloaded, remove it from the list if (i->requested + i->finished + i->writing == 0) { erase_download_piece(i); piece_pos& p = m_piece_map[block.piece_index]; - int prev_prio = p.priority(m_sequenced_download_threshold); - TORRENT_ASSERT(prev_prio < int(m_piece_info.size())); + int prev_prio = p.priority(this); + TORRENT_ASSERT(prev_prio < int(m_priority_boundries.size()) + || m_dirty); p.downloading = 0; - int prio = p.priority(m_sequenced_download_threshold); - if (prev_prio == 0 && prio > 0) add(block.piece_index); - else if (prio > 0) move(prio, p.index); + if (m_sequential_download == -1 && !m_dirty) + { + int prio = p.priority(this); + if (prev_prio == -1 && prio >= 0) add(block.piece_index); + else if (prev_prio >= 0) update(prev_prio, p.index); + } TORRENT_ASSERT(std::find_if(m_downloads.begin(), m_downloads.end() , has_index(block.piece_index)) == m_downloads.end()); diff --git a/libtorrent/src/policy.cpp b/libtorrent/src/policy.cpp index 325007098..2567e2424 100755 --- a/libtorrent/src/policy.cpp +++ b/libtorrent/src/policy.cpp @@ -150,18 +150,7 @@ namespace tcp::endpoint const& m_ep; }; - struct match_peer_id - { - match_peer_id(peer_id const& id_) - : m_id(id_) - {} - - bool operator()(std::pair const& p) const - { return p.second.connection && p.second.connection->pid() == m_id; } - - peer_id const& m_id; - }; - +#ifndef NDEBUG struct match_peer_connection { match_peer_connection(peer_connection const& c) @@ -177,7 +166,7 @@ namespace peer_connection const& m_conn; }; - +#endif } @@ -211,7 +200,7 @@ namespace libtorrent int prefer_whole_pieces = c.prefer_whole_pieces(); - bool rarest_first = t.num_pieces() >= t.settings().initial_picker_threshold; + bool rarest_first = t.num_have() >= t.settings().initial_picker_threshold; if (prefer_whole_pieces == 0) { @@ -224,7 +213,10 @@ namespace libtorrent // the number of blocks we want, but it will try to make the picked // blocks be from whole pieces, possibly by returning more blocks // than we requested. - TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint()); +#ifndef NDEBUG + error_code ec; + TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec); +#endif piece_picker::piece_state_t state; peer_connection::peer_speed_t speed = c.peer_speed(); @@ -241,7 +233,7 @@ namespace libtorrent busy_pieces.reserve(num_requests); std::vector const& suggested = c.suggested_pieces(); - std::vector const& bitfield = c.get_bitfield(); + bitfield const& bits = c.get_bitfield(); if (c.has_peer_choked()) { @@ -251,10 +243,10 @@ namespace libtorrent std::vector const& allowed_fast = c.allowed_fast(); // build a bitmask with only the allowed pieces in it - std::vector mask(c.get_bitfield().size(), false); + bitfield mask(c.get_bitfield().size(), false); for (std::vector::const_iterator i = allowed_fast.begin() , end(allowed_fast.end()); i != end; ++i) - if (bitfield[*i]) mask[*i] = true; + if (bits[*i]) mask.set_bit(*i); p.pick_pieces(mask, interesting_pieces , num_requests, prefer_whole_pieces, c.peer_info_struct() @@ -270,7 +262,7 @@ namespace libtorrent // the last argument is if we should prefer whole pieces // for this peer. If we're downloading one piece in 20 seconds // then use this mode. - p.pick_pieces(bitfield, interesting_pieces + p.pick_pieces(bits, interesting_pieces , num_requests, prefer_whole_pieces, c.peer_info_struct() , state, rarest_first, c.on_parole(), suggested); } @@ -279,7 +271,7 @@ namespace libtorrent (*c.m_logger) << time_now_string() << " PIECE_PICKER [ php: " << prefer_whole_pieces << " picked: " << interesting_pieces.size() << " ]\n"; #endif - std::deque const& dq = c.download_queue(); + std::deque const& dq = c.download_queue(); std::deque const& rq = c.request_queue(); for (std::vector::iterator i = interesting_pieces.begin(); i != interesting_pieces.end(); ++i) @@ -290,7 +282,7 @@ namespace libtorrent { if (num_requests <= 0) break; // don't request pieces we already have in our request queue - if (std::find(dq.begin(), dq.end(), *i) != dq.end() + if (std::find_if(dq.begin(), dq.end(), has_block(*i)) != dq.end() || std::find(rq.begin(), rq.end(), *i) != rq.end()) continue; @@ -315,8 +307,6 @@ namespace libtorrent // that was free. If we couldn't find any busy // blocks as well, we cannot download anything // more from this peer. - - c.send_block_requests(); return; } @@ -337,13 +327,14 @@ namespace libtorrent TORRENT_ASSERT(p.is_requested(*i)); TORRENT_ASSERT(p.num_peers(*i) > 0); c.add_request(*i); - c.send_block_requests(); } policy::policy(torrent* t) - : m_torrent(t) + : m_round_robin(m_peers.end()) + , m_torrent(t) , m_available_free_upload(0) -// , m_last_optimistic_disconnect(min_time()) + , m_num_connect_candidates(0) + , m_num_seeds(0) { TORRENT_ASSERT(t); } // disconnects and removes all peers that are now filtered @@ -364,151 +355,50 @@ namespace libtorrent if (i->second.connection) { - i->second.connection->disconnect(); - if (ses.m_alerts.should_post(alert::info)) - { - ses.m_alerts.post_alert(peer_blocked_alert(i->second.ip.address() - , "disconnected blocked peer")); - } + i->second.connection->disconnect("peer banned by IP filter"); + if (ses.m_alerts.should_post()) + ses.m_alerts.post_alert(peer_blocked_alert(i->second.ip.address())); TORRENT_ASSERT(i->second.connection == 0 || i->second.connection->peer_info_struct() == 0); } else { - if (ses.m_alerts.should_post(alert::info)) - { - ses.m_alerts.post_alert(peer_blocked_alert(i->second.ip.address() - , "blocked peer removed from peer list")); - } + if (ses.m_alerts.should_post()) + ses.m_alerts.post_alert(peer_blocked_alert(i->second.ip.address())); } - if (p) p->clear_peer(&i->second); - m_peers.erase(i++); + erase_peer(i++); } } -/* - // finds the peer that has the worst download rate - // and returns it. May return 0 if all peers are - // choked. - policy::iterator policy::find_choke_candidate() + + // any peer that is erased from m_peers will be + // erased through this function. This way we can make + // sure that any references to the peer are removed + // as well, such as in the piece picker. + void policy::erase_peer(iterator i) { - INVARIANT_CHECK; + if (m_torrent->has_picker()) + m_torrent->picker().clear_peer(&i->second); + if (i->second.seed) --m_num_seeds; + if (is_connect_candidate(i->second, m_torrent->is_finished())) + --m_num_connect_candidates; + if (m_round_robin == i) ++m_round_robin; - iterator worst_peer = m_peers.end(); - size_type min_weight = (std::numeric_limits::min)(); + m_peers.erase(i); + } -#ifndef NDEBUG - int unchoked_counter = m_num_unchoked; -#endif + bool policy::is_connect_candidate(peer const& p, bool finished) + { + if (p.connection + || p.banned + || p.type == peer::not_connectable + || (p.seed && finished) + || p.failcount >= m_torrent->settings().max_failcount) + return false; - // TODO: make this selection better - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->connection; - - if (c == 0) continue; - if (c->is_choked()) continue; -#ifndef NDEBUG - unchoked_counter--; -#endif - if (c->is_disconnecting()) continue; - // if the peer isn't interested, just choke it - if (!c->is_peer_interested()) - return i; - - size_type diff = i->total_download() - - i->total_upload(); - - size_type weight = static_cast(c->statistics().download_rate() * 10.f) - + diff - + ((c->is_interesting() && c->has_peer_choked())?-10:10)*1024; - - if (weight >= min_weight && worst_peer != m_peers.end()) continue; - - min_weight = weight; - worst_peer = i; - continue; - } - TORRENT_ASSERT(unchoked_counter == 0); - return worst_peer; - } - - policy::iterator policy::find_unchoke_candidate() - { - INVARIANT_CHECK; - - // if all of our peers are unchoked, there's - // no left to unchoke - if (m_num_unchoked == m_torrent->num_peers()) - return m_peers.end(); - - iterator unchoke_peer = m_peers.end(); - ptime min_time = libtorrent::min_time(); - float max_down_speed = 0.f; - - // TODO: make this selection better - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->connection; - if (c == 0) continue; - if (c->is_disconnecting()) continue; - if (!c->is_choked()) continue; - if (!c->is_peer_interested()) continue; - if (c->share_diff() < -free_upload_amount - && m_torrent->ratio() != 0) continue; - if (c->statistics().download_rate() < max_down_speed) continue; - - min_time = i->last_optimistically_unchoked; - max_down_speed = c->statistics().download_rate(); - unchoke_peer = i; - } - return unchoke_peer; - } -*/ - policy::iterator policy::find_disconnect_candidate() - { - INVARIANT_CHECK; - - iterator disconnect_peer = m_peers.end(); - double slowest_transfer_rate = (std::numeric_limits::max)(); - - ptime now = time_now(); - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->second.connection; - if (c == 0) continue; - if (c->is_disconnecting()) continue; - - // never disconnect an interesting peer if we have a candidate that - // isn't interesting - if (disconnect_peer != m_peers.end() - && c->is_interesting() - && !disconnect_peer->second.connection->is_interesting()) - continue; - - double transferred_amount - = (double)c->statistics().total_payload_download(); - - time_duration connected_time = now - i->second.connected; - - double connected_time_in_seconds = total_seconds(connected_time); - - double transfer_rate - = transferred_amount / (connected_time_in_seconds + 1); - - // prefer to disconnect uninteresting peers, and secondly slow peers - if (transfer_rate <= slowest_transfer_rate) - { - slowest_transfer_rate = transfer_rate; - disconnect_peer = i; - } - } - return disconnect_peer; + aux::session_impl& ses = m_torrent->session(); + if (ses.m_port_filter.access(p.ip.port()) & port_filter::blocked) + return false; + return true; } policy::iterator policy::find_connect_candidate() @@ -517,16 +407,14 @@ namespace libtorrent // INVARIANT_CHECK; ptime now = time_now(); - ptime min_connect_time(now); iterator candidate = m_peers.end(); - int max_failcount = m_torrent->settings().max_failcount; int min_reconnect_time = m_torrent->settings().min_reconnect_time; - int min_cidr_distance = (std::numeric_limits::max)(); bool finished = m_torrent->is_finished(); - address external_ip = m_torrent->session().m_external_address; + address external_ip = m_torrent->session().external_address(); - if (external_ip == address()) + // don't bias any particular peers when seeding + if (finished || external_ip == address()) { // set external_ip to a random value, to // radomize which peers we prefer @@ -535,237 +423,87 @@ namespace libtorrent external_ip = address_v4(bytes); } - aux::session_impl& ses = m_torrent->session(); + if (m_round_robin == m_peers.end()) m_round_robin = m_peers.begin(); - for (iterator i = m_peers.begin(); i != m_peers.end(); ++i) +#ifndef TORRENT_DISABLE_DHT + bool pinged = false; +#endif + + for (int iterations = (std::min)(int(m_peers.size()), 300); + iterations > 0; --iterations) { - if (i->second.connection) continue; - if (i->second.banned) continue; - if (i->second.type == peer::not_connectable) continue; - if (i->second.seed && finished) continue; - if (i->second.failcount >= max_failcount) continue; + if (m_round_robin == m_peers.end()) m_round_robin = m_peers.begin(); + + peer& pe = m_round_robin->second; + iterator current = m_round_robin; + +#ifndef TORRENT_DISABLE_DHT + // try to send a DHT ping to this peer + // as well, to figure out if it supports + // DHT (uTorrent and BitComet doesn't + // advertise support) + if (!pinged && !pe.added_to_dht) + { + udp::endpoint node(pe.ip.address(), pe.ip.port()); + m_torrent->session().add_dht_node(node); + pe.added_to_dht = true; + pinged = true; + } +#endif + // if the number of peers is growing large + // we need to start weeding. + // don't remove peers we're connected to + // don't remove peers we've never even tried + // don't remove banned peers unless they're 2 + // hours old. They should remain banned for + // at least that long + // don't remove peers that we still can try again + if (pe.connection == 0 + && pe.connected != min_time() + && (!pe.banned || now - pe.connected > hours(2)) + && !is_connect_candidate(pe, finished) + && m_peers.size() >= m_torrent->settings().max_peerlist_size * 0.9) + { + erase_peer(m_round_robin++); + continue; + } + + ++m_round_robin; + + if (!is_connect_candidate(pe, finished)) continue; - // prefer peers with lower failcount if (candidate != m_peers.end() - && candidate->second.failcount < i->second.failcount) + && !compare_peer(candidate->second, pe, external_ip)) continue; + + if (now - pe.connected < + seconds((pe.failcount + 1) * min_reconnect_time)) continue; - if (now - i->second.connected < seconds((i->second.failcount + 1) * min_reconnect_time)) - continue; - if (ses.m_port_filter.access(i->second.ip.port()) & port_filter::blocked) - continue; - - TORRENT_ASSERT(i->second.connected <= now); - - if (i->second.connected > min_connect_time) continue; - int distance = cidr_distance(external_ip, i->second.ip.address()); - if (distance > min_cidr_distance) continue; - - min_cidr_distance = distance; - min_connect_time = i->second.connected; - candidate = i; + candidate = current; } - TORRENT_ASSERT(min_connect_time <= now); - #if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING if (candidate != m_peers.end()) { - (*m_torrent->session().m_logger) << "*** FOUND CONNECTION CANDIDATE [" + (*m_torrent->session().m_logger) << time_now_string() + << " *** FOUND CONNECTION CANDIDATE [" " ip: " << candidate->second.ip << - " d: " << min_cidr_distance << + " d: " << cidr_distance(external_ip, candidate->second.ip.address()) << " external: " << external_ip << - " t: " << total_seconds(time_now() - min_connect_time) << + " t: " << total_seconds(time_now() - candidate->second.connected) << " ]\n"; } #endif return candidate; } -/* - policy::iterator policy::find_seed_choke_candidate() - { - INVARIANT_CHECK; - TORRENT_ASSERT(m_num_unchoked > 0); - // first choice candidate. - // it is a candidate we owe nothing to and which has been unchoked - // the longest. - iterator candidate = m_peers.end(); - - // not valid when candidate == 0 - ptime last_unchoke = min_time(); - - // second choice candidate. - // if there is no first choice candidate, this candidate will be chosen. - // it is the candidate that we owe the least to. - iterator second_candidate = m_peers.end(); - size_type lowest_share_diff = 0; // not valid when secondCandidate==0 - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->connection; - // ignore peers that are choked or - // whose connection is closed - if (c == 0) continue; - - if (c->is_choked()) continue; - if (c->is_disconnecting()) continue; - - size_type share_diff = c->share_diff(); - - // select as second candidate the one that we owe the least - // to - if (second_candidate == m_peers.end() - || share_diff <= lowest_share_diff) - { - lowest_share_diff = share_diff; - second_candidate = i; - } - - // select as first candidate the one that we don't owe anything to - // and has been waiting for an unchoke the longest - if (share_diff > 0) continue; - if (candidate == m_peers.end() - || last_unchoke > i->last_optimistically_unchoked) - { - last_unchoke = i->last_optimistically_unchoked; - candidate = i; - } - } - if (candidate != m_peers.end()) return candidate; - TORRENT_ASSERT(second_candidate != m_peers.end()); - return second_candidate; - } - - policy::iterator policy::find_seed_unchoke_candidate() - { - INVARIANT_CHECK; - - iterator candidate = m_peers.end(); - ptime last_unchoke = time_now(); - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->connection; - if (c == 0) continue; - if (!c->is_choked()) continue; - if (!c->is_peer_interested()) continue; - if (c->is_disconnecting()) continue; - if (last_unchoke < i->last_optimistically_unchoked) continue; - last_unchoke = i->last_optimistically_unchoked; - candidate = i; - } - return candidate; - } - - bool policy::seed_unchoke_one_peer() - { - INVARIANT_CHECK; - - iterator p = find_seed_unchoke_candidate(); - if (p != m_peers.end()) - { - TORRENT_ASSERT(p->connection->is_choked()); - p->connection->send_unchoke(); - p->last_optimistically_unchoked = time_now(); - ++m_num_unchoked; - } - return p != m_peers.end(); - } - - void policy::seed_choke_one_peer() - { - INVARIANT_CHECK; - - iterator p = find_seed_choke_candidate(); - if (p != m_peers.end()) - { - TORRENT_ASSERT(!p->connection->is_choked()); - p->connection->send_choke(); - --m_num_unchoked; - } - } -*/ void policy::pulse() { INVARIANT_CHECK; if (m_torrent->is_paused()) return; - piece_picker* p = 0; - if (m_torrent->has_picker()) - p = &m_torrent->picker(); - - ptime now = time_now(); - // remove old disconnected peers from the list - for (iterator i = m_peers.begin(); i != m_peers.end();) - { - // this timeout has to be customizable! - // don't remove banned peers, they should - // remain banned - if (i->second.connection == 0 - && i->second.connected != min_time() - && !i->second.banned - && now - i->second.connected > minutes(120)) - { - if (p) p->clear_peer(&i->second); - m_peers.erase(i++); - } - else - { - ++i; - } - } - - // ------------------------------------- - // maintain the number of connections - // ------------------------------------- -/* - // count the number of connected peers except for peers - // that are currently in the process of disconnecting - int num_connected_peers = 0; - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - if (i->connection && !i->connection->is_disconnecting()) - ++num_connected_peers; - } - - if (m_torrent->max_connections() != (std::numeric_limits::max)()) - { - int max_connections = m_torrent->max_connections(); - - if (num_connected_peers >= max_connections) - { - // every minute, disconnect the worst peer in hope of finding a better peer - - ptime local_time = time_now(); - if (m_last_optimistic_disconnect + seconds(120) <= local_time - && find_connect_candidate() != m_peers.end()) - { - m_last_optimistic_disconnect = local_time; - --max_connections; // this will have the effect of disconnecting the worst peer - } - } - else - { - // don't do a disconnect earlier than 1 minute after some peer was connected - m_last_optimistic_disconnect = time_now(); - } - - while (num_connected_peers > max_connections) - { - bool ret = disconnect_one_peer(); - (void)ret; - TORRENT_ASSERT(ret); - --num_connected_peers; - } - } -*/ // ------------------------ // upload shift // ------------------------ @@ -796,142 +534,9 @@ namespace libtorrent , m_torrent->end() , m_available_free_upload); } -/* - // ------------------------ - // seed choking policy - // ------------------------ - if (m_torrent->is_seed()) - { - if (m_num_unchoked > m_torrent->m_uploads_quota.given) - { - do - { - iterator p = find_seed_choke_candidate(); - --m_num_unchoked; - TORRENT_ASSERT(p != m_peers.end()); - if (p == m_peers.end()) break; - - TORRENT_ASSERT(!p->connection->is_choked()); - p->connection->send_choke(); - } while (m_num_unchoked > m_torrent->m_uploads_quota.given); - } - else if (m_num_unchoked > 0) - { - // optimistic unchoke. trade the 'worst' - // unchoked peer with one of the choked - // TODO: This rotation should happen - // far less frequent than this! - TORRENT_ASSERT(m_num_unchoked <= m_torrent->num_peers()); - iterator p = find_seed_unchoke_candidate(); - if (p != m_peers.end()) - { - TORRENT_ASSERT(p->connection->is_choked()); - seed_choke_one_peer(); - p->connection->send_unchoke(); - ++m_num_unchoked; - } - - } - - // make sure we have enough - // unchoked peers - while (m_num_unchoked < m_torrent->m_uploads_quota.given) - { - if (!seed_unchoke_one_peer()) break; - } -#ifndef NDEBUG - check_invariant(); -#endif - } - - // ---------------------------- - // downloading choking policy - // ---------------------------- - else - { - if (m_torrent->ratio() != 0) - { - // choke peers that have leeched too much without giving anything back - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->connection; - if (c == 0) continue; - - size_type diff = i->connection->share_diff(); - if (diff < -free_upload_amount - && !c->is_choked()) - { - // if we have uploaded more than a piece for free, choke peer and - // wait until we catch up with our download. - c->send_choke(); - --m_num_unchoked; - } - } - } - - if (m_torrent->m_uploads_quota.given < m_torrent->num_peers()) - { - TORRENT_ASSERT(m_torrent->m_uploads_quota.given >= 0); - - // make sure we don't have too many - // unchoked peers - if (m_num_unchoked > m_torrent->m_uploads_quota.given) - { - do - { - iterator p = find_choke_candidate(); - if (p == m_peers.end()) break; - TORRENT_ASSERT(p != m_peers.end()); - TORRENT_ASSERT(!p->connection->is_choked()); - p->connection->send_choke(); - --m_num_unchoked; - } while (m_num_unchoked > m_torrent->m_uploads_quota.given); - } - // this should prevent the choke/unchoke - // problem, since it will not unchoke unless - // there actually are any choked peers - else if (count_choked() > 0) - { - // optimistic unchoke. trade the 'worst' - // unchoked peer with one of the choked - TORRENT_ASSERT(m_num_unchoked <= m_torrent->num_peers()); - iterator p = find_unchoke_candidate(); - if (p != m_peers.end()) - { - TORRENT_ASSERT(p->connection->is_choked()); - choke_one_peer(); - p->connection->send_unchoke(); - ++m_num_unchoked; - } - } - } - - // make sure we have enough - // unchoked peers - while (m_num_unchoked < m_torrent->m_uploads_quota.given - && unchoke_one_peer()); - } -*/ } - int policy::count_choked() const - { - int ret = 0; - for (const_iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - if (!i->second.connection - || i->second.connection->is_connecting() - || i->second.connection->is_disconnecting() - || !i->second.connection->is_peer_interested()) - continue; - if (i->second.connection->is_choked()) ++ret; - } - return ret; - } - - void policy::new_connection(peer_connection& c) + bool policy::new_connection(peer_connection& c) { TORRENT_ASSERT(!c.is_local()); @@ -943,16 +548,20 @@ namespace libtorrent // TODO: only allow _one_ connection to use this // override at a time - TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint()); + error_code ec; + TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec); + aux::session_impl& ses = m_torrent->session(); + if (m_torrent->num_peers() >= m_torrent->max_connections() - && m_torrent->session().num_connections() >= m_torrent->session().max_connections() + && ses.num_connections() >= ses.max_connections() && c.remote().address() != m_torrent->current_tracker().address()) { - throw protocol_error("too many connections, refusing incoming connection"); // cause a disconnect + c.disconnect("too many connections, refusing incoming connection"); + return false; } -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING if (c.remote().address() == m_torrent->current_tracker().address()) { m_torrent->debug_log("overriding connection limit for tracker NAT-check"); @@ -977,36 +586,86 @@ namespace libtorrent if (i != m_peers.end()) { if (i->second.banned) - throw protocol_error("ip address banned, closing"); + { + c.disconnect("ip address banned, closing"); + return false; + } if (i->second.connection != 0) { + boost::shared_ptr other_socket + = i->second.connection->get_socket(); + boost::shared_ptr this_socket + = c.get_socket(); + + error_code ec1; + error_code ec2; + bool self_connection = + other_socket->remote_endpoint(ec2) == this_socket->local_endpoint(ec1) + || other_socket->local_endpoint(ec2) == this_socket->remote_endpoint(ec1); + + if (ec1) + { + c.disconnect(ec1.message().c_str()); + return false; + } + + if (self_connection) + { + c.disconnect("connected to ourselves", 1); + i->second.connection->disconnect("connected to ourselves", 1); + return false; + } + TORRENT_ASSERT(i->second.connection != &c); // the new connection is a local (outgoing) connection // or the current one is already connected - if (!i->second.connection->is_connecting() || c.is_local()) + if (ec2) { - throw protocol_error("duplicate connection, closing"); + i->second.connection->disconnect(ec2.message().c_str()); + } + else if (!i->second.connection->is_connecting() || c.is_local()) + { + c.disconnect("duplicate connection, closing"); + return false; } else { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING m_torrent->debug_log("duplicate connection. existing connection" " is connecting and this connection is incoming. closing existing " "connection in favour of this one"); #endif - i->second.connection->disconnect(); + i->second.connection->disconnect("incoming duplicate connection " + "with higher priority, closing"); } } + + if (m_num_connect_candidates > 0) + --m_num_connect_candidates; } else { // we don't have any info about this peer. // add a new entry - TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint()); + error_code ec; + TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec); + + if (int(m_peers.size()) >= m_torrent->settings().max_peerlist_size) + { + c.disconnect("peer list size exceeded, refusing incoming connection"); + return false; + } peer p(c.remote(), peer::not_connectable, 0); i = m_peers.insert(std::make_pair(c.remote().address(), p)); +#ifndef TORRENT_DISABLE_GEO_IP + int as = ses.as_for_ip(c.remote().address()); +#ifndef NDEBUG + i->second.inet_as_num = as; +#endif + i->second.inet_as = ses.lookup_as(as); +#endif } c.set_peer_info(&i->second); @@ -1018,13 +677,15 @@ namespace libtorrent TORRENT_ASSERT(i->second.connection); if (!c.fast_reconnect()) i->second.connected = time_now(); -// m_last_optimistic_disconnect = time_now(); + return true; } - void policy::update_peer_port(int port, policy::peer* p, int src) + bool policy::update_peer_port(int port, policy::peer* p, int src) { TORRENT_ASSERT(p != 0); - if (p->ip.port() == port) return; + TORRENT_ASSERT(p->connection); + + if (p->ip.port() == port) return true; if (m_torrent->settings().allow_multiple_connections_per_ip) { @@ -1037,26 +698,44 @@ namespace libtorrent policy::peer& pp = i->second; if (pp.connection) { - throw protocol_error("duplicate connection"); + p->connection->disconnect("duplicate connection"); + return false; } - if (m_torrent->has_picker()) - m_torrent->picker().clear_peer(&i->second); - m_peers.erase(i); + erase_peer(i); } } else { TORRENT_ASSERT(m_peers.count(p->ip.address()) == 1); } + bool was_conn_cand = is_connect_candidate(*p, m_torrent->is_finished()); p->ip.port(port); p->source |= src; + + if (was_conn_cand != is_connect_candidate(*p, m_torrent->is_finished())) + { + m_num_connect_candidates += was_conn_cand ? -1 : 1; + if (m_num_connect_candidates < 0) m_num_connect_candidates = 0; + } + return true; + } + + bool policy::has_peer(policy::peer const* p) const + { + // find p in m_peers + for (std::multimap::const_iterator i = m_peers.begin() + , end(m_peers.end()); i != end; ++i) + { + if (&i->second == p) return true; + } + return false; } policy::peer* policy::peer_from_tracker(tcp::endpoint const& remote, peer_id const& pid , int src, char flags) { -// too expensive -// INVARIANT_CHECK; + // way too expensive + //INVARIANT_CHECK; // just ignore the obviously invalid entries if (remote.address() == address() || remote.port() == 0) @@ -1067,125 +746,110 @@ namespace libtorrent port_filter const& pf = ses.m_port_filter; if (pf.access(remote.port()) & port_filter::blocked) { - if (ses.m_alerts.should_post(alert::info)) - { - ses.m_alerts.post_alert(peer_blocked_alert(remote.address() - , "outgoing port blocked, peer not added to peer list")); - } + if (ses.m_alerts.should_post()) + ses.m_alerts.post_alert(peer_blocked_alert(remote.address())); return 0; } - try + iterator i; + + if (m_torrent->settings().allow_multiple_connections_per_ip) { - iterator i; - - if (m_torrent->settings().allow_multiple_connections_per_ip) + std::pair range = m_peers.equal_range(remote.address()); + i = std::find_if(range.first, range.second, match_peer_endpoint(remote)); + if (i == range.second) i = m_peers.end(); + } + else + { + i = m_peers.find(remote.address()); + } + + if (i == m_peers.end()) + { + // if the IP is blocked, don't add it + if (ses.m_ip_filter.access(remote.address()) & ip_filter::blocked) { - std::pair range = m_peers.equal_range(remote.address()); - i = std::find_if(range.first, range.second, match_peer_endpoint(remote)); - if (i == range.second) i = m_peers.end(); - } - else - { - i = m_peers.find(remote.address()); - } - - if (i == m_peers.end()) - { - // if the IP is blocked, don't add it - if (ses.m_ip_filter.access(remote.address()) & ip_filter::blocked) + if (ses.m_alerts.should_post()) { - if (ses.m_alerts.should_post(alert::info)) - { - ses.m_alerts.post_alert(peer_blocked_alert(remote.address() - , "blocked peer not added to peer list")); - } - return 0; + ses.m_alerts.post_alert(peer_blocked_alert(remote.address())); } - - // we don't have any info about this peer. - // add a new entry - i = m_peers.insert(std::make_pair(remote.address() + return 0; + } + + if (int(m_peers.size()) >= m_torrent->settings().max_peerlist_size) + return 0; + + // we don't have any info about this peer. + // add a new entry + i = m_peers.insert(std::make_pair(remote.address() , peer(remote, peer::connectable, src))); #ifndef TORRENT_DISABLE_ENCRYPTION - if (flags & 0x01) i->second.pe_support = true; + if (flags & 0x01) i->second.pe_support = true; #endif - if (flags & 0x02) i->second.seed = true; - } - else + if (flags & 0x02) { - i->second.type = peer::connectable; + i->second.seed = true; + ++m_num_seeds; + } - i->second.ip = remote; - i->second.source |= src; +#ifndef TORRENT_DISABLE_GEO_IP + int as = ses.as_for_ip(remote.address()); +#ifndef NDEBUG + i->second.inet_as_num = as; +#endif + i->second.inet_as = ses.lookup_as(as); +#endif + if (is_connect_candidate(i->second, m_torrent->is_finished())) + ++m_num_connect_candidates; + } + else + { + bool was_conn_cand = is_connect_candidate(i->second, m_torrent->is_finished()); + + i->second.type = peer::connectable; + + i->second.ip = remote; + i->second.source |= src; - // if this peer has failed before, decrease the - // counter to allow it another try, since somebody - // else is appearantly able to connect to it - // if it comes from the DHT it might be stale though - if (i->second.failcount > 0 && src != peer_info::dht) - --i->second.failcount; + // if this peer has failed before, decrease the + // counter to allow it another try, since somebody + // else is appearantly able to connect to it + // only trust this if it comes from the tracker + if (i->second.failcount > 0 && src == peer_info::tracker) + --i->second.failcount; - // if we're connected to this peer - // we already know if it's a seed or not - // so we don't have to trust this source - if ((flags & 0x02) && !i->second.connection) i->second.seed = true; + // if we're connected to this peer + // we already know if it's a seed or not + // so we don't have to trust this source + if ((flags & 0x02) && !i->second.connection) + { + if (!i->second.seed) ++m_num_seeds; + i->second.seed = true; + } -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (i->second.connection) - { - // this means we're already connected - // to this peer. don't connect to - // it again. +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING + if (i->second.connection) + { + // this means we're already connected + // to this peer. don't connect to + // it again. - m_torrent->debug_log("already connected to peer: " + remote.address().to_string() + ":" - + boost::lexical_cast(remote.port()) + " " - + boost::lexical_cast(i->second.connection->pid())); + m_torrent->debug_log("already connected to peer: " + remote.address().to_string() + ":" + + boost::lexical_cast(remote.port()) + " " + + boost::lexical_cast(i->second.connection->pid())); - TORRENT_ASSERT(i->second.connection->associated_torrent().lock().get() == m_torrent); - } + TORRENT_ASSERT(i->second.connection->associated_torrent().lock().get() == m_torrent); + } #endif - } - return &i->second; - } - catch(std::exception& e) - { - if (m_torrent->alerts().should_post(alert::debug)) + + if (was_conn_cand != is_connect_candidate(i->second, m_torrent->is_finished())) { - m_torrent->alerts().post_alert( - peer_error_alert(remote, pid, e.what())); + m_num_connect_candidates += was_conn_cand ? -1 : 1; + if (m_num_connect_candidates < 0) m_num_connect_candidates = 0; } } - return 0; - } - // this is called when we are choked by a peer - // i.e. a peer lets us know that we will not receive - // anything for a while - void policy::choked(peer_connection&) - { - } - - void policy::piece_finished(int index, bool successfully_verified) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(index >= 0 && index < m_torrent->torrent_file().num_pieces()); - - if (successfully_verified) - { - // have all peers update their interested-flag - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - if (i->second.connection == 0) continue; - // if we're not interested, we will not become interested - if (!i->second.connection->is_interesting()) continue; - if (!i->second.connection->has_piece(index)) continue; - - i->second.connection->update_interest(); - } - } + return &i->second; } // this is called when we are unchoked by a peer @@ -1197,6 +861,7 @@ namespace libtorrent if (c.is_interesting()) { request_a_block(*m_torrent, c); + c.send_block_requests(); } } @@ -1209,6 +874,8 @@ namespace libtorrent , boost::bind(std::equal_to(), bind(&peer::connection , bind(&iterator::value_type::second, _1)), &c)) != m_peers.end()); + aux::session_impl& ses = m_torrent->session(); + // if the peer is choked and we have upload slots left, // then unchoke it. Another condition that has to be met // is that the torrent doesn't keep track of the individual @@ -1220,23 +887,23 @@ namespace libtorrent // In that case we don't care if people are leeching, they // can't pay for their downloads anyway. if (c.is_choked() - && m_torrent->session().num_uploads() < m_torrent->session().max_uploads() + && ses.num_uploads() < ses.max_uploads() && (m_torrent->ratio() == 0 || c.share_diff() >= -free_upload_amount || m_torrent->is_finished())) { - m_torrent->session().unchoke_peer(c); + ses.unchoke_peer(c); } -#if defined(TORRENT_VERBOSE_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING else if (c.is_choked()) { std::string reason; - if (m_torrent->session().num_uploads() >= m_torrent->session().max_uploads()) + if (ses.num_uploads() >= ses.max_uploads()) { reason = "the number of uploads (" - + boost::lexical_cast(m_torrent->session().num_uploads()) + + boost::lexical_cast(ses.num_uploads()) + ") is more than or equal to the limit (" - + boost::lexical_cast(m_torrent->session().max_uploads()) + + boost::lexical_cast(ses.max_uploads()) + ")"; } else @@ -1326,45 +993,19 @@ namespace libtorrent TORRENT_ASSERT(!p->second.connection); TORRENT_ASSERT(p->second.type == peer::connectable); - try + TORRENT_ASSERT(is_connect_candidate(p->second, m_torrent->is_finished())); + if (!m_torrent->connect_to_peer(&p->second)) { - if (!m_torrent->connect_to_peer(&p->second)) - { - ++p->second.failcount; - return false; - } - p->second.connection->add_stat(p->second.prev_amount_download, p->second.prev_amount_upload); - p->second.prev_amount_download = 0; - p->second.prev_amount_upload = 0; - return true; - } - catch (std::exception& e) - { -#if defined(TORRENT_VERBOSE_LOGGING) - (*m_torrent->session().m_logger) << "*** CONNECTION FAILED '" - << e.what() << "'\n"; -#endif - std::cerr << e.what() << std::endl; ++p->second.failcount; return false; } - } - - bool policy::disconnect_one_peer() - { - iterator p = find_disconnect_candidate(); - if (p == m_peers.end()) - return false; -#if defined(TORRENT_VERBOSE_LOGGING) - (*p->second.connection->m_logger) << "*** CLOSING CONNECTION 'too many connections'\n"; -#endif - - p->second.connection->disconnect(); + TORRENT_ASSERT(!is_connect_candidate(p->second, m_torrent->is_finished())); + --m_num_connect_candidates; return true; } // this is called whenever a peer connection is closed - void policy::connection_closed(const peer_connection& c) throw() + void policy::connection_closed(const peer_connection& c) { // too expensive // INVARIANT_CHECK; @@ -1397,6 +1038,9 @@ namespace libtorrent // p->connected = time_now(); } + if (is_connect_candidate(*p, m_torrent->is_finished())) + ++m_num_connect_candidates; + // if the share ratio is 0 (infinite), the // m_available_free_upload isn't used, // because it isn't necessary. @@ -1406,6 +1050,8 @@ namespace libtorrent TORRENT_ASSERT(c.share_diff() < (std::numeric_limits::max)()); m_available_free_upload += c.share_diff(); } + TORRENT_ASSERT(p->prev_amount_upload == 0); + TORRENT_ASSERT(p->prev_amount_download == 0); p->prev_amount_download += c.statistics().total_payload_download(); p->prev_amount_upload += c.statistics().total_payload_upload(); } @@ -1419,6 +1065,7 @@ namespace libtorrent && c.allowed_fast().empty()) return; request_a_block(*m_torrent, c); + c.send_block_requests(); } #ifndef NDEBUG @@ -1428,8 +1075,8 @@ namespace libtorrent // INVARIANT_CHECK; TORRENT_ASSERT(c); - try { TORRENT_ASSERT(c->remote() == c->get_socket()->remote_endpoint()); } - catch (std::exception&) {} + error_code ec; + TORRENT_ASSERT(c->remote() == c->get_socket()->remote_endpoint(ec) || ec); return std::find_if( m_peers.begin() @@ -1439,6 +1086,7 @@ namespace libtorrent void policy::check_invariant() const { + TORRENT_ASSERT(m_num_connect_candidates >= 0); if (m_torrent->is_aborted()) return; int connected_peers = 0; @@ -1451,6 +1099,9 @@ namespace libtorrent i != m_peers.end(); ++i) { peer const& p = i->second; +#ifndef TORRENT_DISABLE_GEO_IP + TORRENT_ASSERT(p.inet_as == 0 || p.inet_as->first == p.inet_as_num); +#endif if (!m_torrent->settings().allow_multiple_connections_per_ip) { TORRENT_ASSERT(m_peers.count(p.ip.address()) == 1); @@ -1467,6 +1118,8 @@ namespace libtorrent { continue; } + TORRENT_ASSERT(p.prev_amount_upload == 0); + TORRENT_ASSERT(p.prev_amount_download == 0); if (p.optimistically_unchoked) { TORRENT_ASSERT(p.connection); @@ -1536,25 +1189,32 @@ namespace libtorrent policy::peer::peer(const tcp::endpoint& ip_, peer::connection_type t, int src) : ip(ip_) +#ifndef TORRENT_DISABLE_GEO_IP + , inet_as(0) +#endif + , failcount(0) + , trust_points(0) + , source(src) + , hashfails(0) , type(t) + , fast_reconnects(0) #ifndef TORRENT_DISABLE_ENCRYPTION , pe_support(true) #endif - , failcount(0) - , hashfails(0) - , seed(false) - , fast_reconnects(0) , optimistically_unchoked(false) - , last_optimistically_unchoked(min_time()) - , connected(min_time()) - , trust_points(0) + , seed(false) , on_parole(false) + , banned(false) +#ifndef TORRENT_DISABLE_DHT + , added_to_dht(false) +#endif + , connection(0) , prev_amount_upload(0) , prev_amount_download(0) - , banned(false) - , source(src) - , connection(0) + , last_optimistically_unchoked(min_time()) + , connected(min_time()) { + TORRENT_ASSERT((src & 0xff) == src); TORRENT_ASSERT(connected < time_now()); } @@ -1583,5 +1243,36 @@ namespace libtorrent return prev_amount_upload; } } + + // this returns true if lhs is a better connect candidate than rhs + bool policy::compare_peer(policy::peer const& lhs, policy::peer const& rhs + , address const& external_ip) const + { + // prefer peers with lower failcount + if (lhs.failcount != rhs.failcount) + return lhs.failcount < rhs.failcount; + + // Local peers should always be tried first + bool lhs_local = is_local(lhs.ip.address()); + bool rhs_local = is_local(rhs.ip.address()); + if (lhs_local != rhs_local) return lhs_local > rhs_local; + + if (lhs.connected != rhs.connected) + return lhs.connected < rhs.connected; + +#ifndef TORRENT_DISABLE_GEO_IP + // don't bias fast peers when seeding + if (!m_torrent->is_finished() && m_torrent->session().has_asnum_db()) + { + int lhs_as = lhs.inet_as ? lhs.inet_as->second : 0; + int rhs_as = rhs.inet_as ? rhs.inet_as->second : 0; + if (lhs_as != rhs_as) return lhs_as > rhs_as; + } +#endif + int lhs_distance = cidr_distance(external_ip, lhs.ip.address()); + int rhs_distance = cidr_distance(external_ip, rhs.ip.address()); + if (lhs_distance < rhs_distance) return true; + return false; + } } diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp index 331ffa377..5e0ad1205 100755 --- a/libtorrent/src/session.cpp +++ b/libtorrent/src/session.cpp @@ -80,6 +80,11 @@ using boost::bind; using boost::mutex; using libtorrent::aux::session_impl; +#ifdef TORRENT_MEMDEBUG +void start_malloc_debug(); +void stop_malloc_debug(); +#endif + namespace libtorrent { @@ -107,16 +112,19 @@ namespace libtorrent fingerprint const& id , std::pair listen_port_range , char const* listen_interface -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , fs::path logpath #endif ) : m_impl(new session_impl(listen_port_range, id, listen_interface -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , logpath #endif )) { +#ifdef TORRENT_MEMDEBUG + start_malloc_debug(); +#endif // turn off the filename checking in boost.filesystem TORRENT_ASSERT(listen_port_range.first > 0); TORRENT_ASSERT(listen_port_range.first < listen_port_range.second); @@ -130,16 +138,19 @@ namespace libtorrent } session::session(fingerprint const& id -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , fs::path logpath #endif ) -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING : m_impl(new session_impl(std::make_pair(0, 0), id, "0.0.0.0", logpath)) #else : m_impl(new session_impl(std::make_pair(0, 0), id, "0.0.0.0")) #endif { +#ifdef TORRENT_MEMDEBUG + start_malloc_debug(); +#endif #ifndef NDEBUG boost::function0 test = boost::ref(*m_impl); TORRENT_ASSERT(!test.empty()); @@ -148,6 +159,9 @@ namespace libtorrent session::~session() { +#ifdef TORRENT_MEMDEBUG + stop_malloc_debug(); +#endif TORRENT_ASSERT(m_impl); // if there is at least one destruction-proxy // abort the session and let the destructor @@ -161,6 +175,35 @@ namespace libtorrent m_impl->add_extension(ext); } +#ifndef TORRENT_DISABLE_GEO_IP + bool session::load_asnum_db(char const* file) + { + return m_impl->load_asnum_db(file); + } + + bool session::load_country_db(char const* file) + { + return m_impl->load_country_db(file); + } + + int session::as_for_ip(address const& addr) + { + aux::session_impl::mutex_t::scoped_lock l(m_impl->m_mutex); + return m_impl->as_for_ip(addr); + } + +#endif + + void session::load_state(entry const& ses_state) + { + m_impl->load_state(ses_state); + } + + entry session::state() const + { + return m_impl->state(); + } + void session::set_ip_filter(ip_filter const& f) { m_impl->set_ip_filter(f); @@ -196,6 +239,10 @@ namespace libtorrent return m_impl->find_torrent_handle(info_hash); } + torrent_handle session::add_torrent(add_torrent_params const& params) + { + return m_impl->add_torrent(params); + } // if the torrent already exists, this will throw duplicate_torrent torrent_handle session::add_torrent( @@ -206,10 +253,19 @@ namespace libtorrent , bool paused , storage_constructor_type sc) { - TORRENT_ASSERT(!ti.m_half_metadata); boost::intrusive_ptr tip(new torrent_info(ti)); - return m_impl->add_torrent(tip, save_path, resume_data - , storage_mode, sc, paused, 0); + add_torrent_params p(sc); + p.ti = tip; + p.save_path = save_path; + std::vector buf; + if (resume_data.type() != entry::undefined_t) + { + bencode(std::back_inserter(buf), resume_data); + p.resume_data = &buf; + } + p.storage_mode = storage_mode; + p.paused = paused; + return m_impl->add_torrent(p); } torrent_handle session::add_torrent( @@ -221,9 +277,19 @@ namespace libtorrent , storage_constructor_type sc , void* userdata) { - TORRENT_ASSERT(!ti->m_half_metadata); - return m_impl->add_torrent(ti, save_path, resume_data - , storage_mode, sc, paused, userdata); + add_torrent_params p(sc); + p.ti = ti; + p.save_path = save_path; + std::vector buf; + if (resume_data.type() != entry::undefined_t) + { + bencode(std::back_inserter(buf), resume_data); + p.resume_data = &buf; + } + p.storage_mode = storage_mode; + p.paused = paused; + p.userdata = userdata; + return m_impl->add_torrent(p); } torrent_handle session::add_torrent( @@ -237,8 +303,13 @@ namespace libtorrent , storage_constructor_type sc , void* userdata) { - return m_impl->add_torrent(tracker_url, info_hash, name, save_path, e - , storage_mode, sc, paused, userdata); + add_torrent_params p(sc); + p.tracker_url = tracker_url; + p.info_hash = info_hash; + p.save_path = save_path; + p.paused = paused; + p.userdata = userdata; + return m_impl->add_torrent(p); } void session::remove_torrent(const torrent_handle& h, int options) @@ -263,6 +334,21 @@ namespace libtorrent return m_impl->status(); } + void session::pause() { m_impl->pause(); } + void session::resume() { m_impl->resume(); } + bool session::is_paused() const { return m_impl->is_paused(); } + + void session::get_cache_info(sha1_hash const& ih + , std::vector& ret) const + { + m_impl->m_disk_thread.get_cache_info(ih, ret); + } + + cache_status session::get_cache_status() const + { + return m_impl->m_disk_thread.status(); + } + #ifndef TORRENT_DISABLE_DHT void session::start_dht(entry const& startup_state) @@ -427,9 +513,27 @@ namespace libtorrent return m_impl->wait_for_alert(max_wait); } + void session::set_alert_mask(int m) + { + m_impl->set_alert_mask(m); + } + void session::set_severity_level(alert::severity_t s) { - m_impl->set_severity_level(s); + int m = 0; + switch (s) + { + case alert::debug: m = alert::all_categories; break; + case alert::info: m = alert::all_categories & ~(alert::debug_notification + | alert::progress_notification); break; + case alert::warning: m = alert::all_categories & ~(alert::debug_notification + | alert::status_notification | alert::progress_notification); break; + case alert::critical: m = alert::error_notification | alert::storage_notification; break; + case alert::fatal: m = alert::error_notification; break; + default: break; + } + + m_impl->set_alert_mask(m); } void session::start_lsd() @@ -437,14 +541,14 @@ namespace libtorrent m_impl->start_lsd(); } - void session::start_natpmp() + natpmp* session::start_natpmp() { - m_impl->start_natpmp(); + return m_impl->start_natpmp(); } - void session::start_upnp() + upnp* session::start_upnp() { - m_impl->start_upnp(); + return m_impl->start_upnp(); } void session::stop_lsd() diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index 800422d63..c2a87c73d 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -74,6 +74,11 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/session_impl.hpp" #include "libtorrent/kademlia/dht_tracker.hpp" #include "libtorrent/enum_net.hpp" +#include "libtorrent/config.hpp" + +#ifndef TORRENT_WINDOWS +#include +#endif #ifndef TORRENT_DISABLE_ENCRYPTION @@ -116,423 +121,8 @@ namespace detail } - } namespace aux { - // This is the checker thread - // it is looping in an infinite loop - // until the session is aborted. It will - // normally just block in a wait() call, - // waiting for a signal from session that - // there's a new torrent to check. - - void checker_impl::operator()() - { - eh_initializer(); - // if we're currently performing a full file check, - // this is the torrent being processed - boost::shared_ptr processing; - boost::shared_ptr t; - for (;;) - { - // temporary torrent used while checking fastresume data - try - { - t.reset(); - { - boost::mutex::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - // if the job queue is empty and - // we shouldn't abort - // wait for a signal - while (m_torrents.empty() && !m_abort && !processing) - m_cond.wait(l); - - if (m_abort) - { - // no lock is needed here, because the main thread - // has already been shut down by now - processing.reset(); - t.reset(); - std::for_each(m_torrents.begin(), m_torrents.end() - , boost::bind(&torrent::abort - , boost::bind(&shared_ptr::get - , boost::bind(&piece_checker_data::torrent_ptr, _1)))); - m_torrents.clear(); - std::for_each(m_processing.begin(), m_processing.end() - , boost::bind(&torrent::abort - , boost::bind(&shared_ptr::get - , boost::bind(&piece_checker_data::torrent_ptr, _1)))); - m_processing.clear(); - return; - } - - if (!m_torrents.empty()) - { - t = m_torrents.front(); - if (t->abort) - { - // make sure the locking order is - // consistent to avoid dead locks - // we need to lock the session because closing - // torrents assume to have access to it - l.unlock(); - session_impl::mutex_t::scoped_lock l2(m_ses.m_mutex); - l.lock(); - - t->torrent_ptr->abort(); - m_torrents.pop_front(); - continue; - } - } - } - - if (t) - { - std::string error_msg; - t->parse_resume_data(t->resume_data, t->torrent_ptr->torrent_file() - , error_msg); - - // lock the session to add the new torrent - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - if (!error_msg.empty() && m_ses.m_alerts.should_post(alert::warning)) - { - m_ses.m_alerts.post_alert(fastresume_rejected_alert( - t->torrent_ptr->get_handle() - , error_msg)); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "fastresume data for " - << t->torrent_ptr->torrent_file().name() << " rejected: " - << error_msg << "\n"; -#endif - } - - mutex::scoped_lock l2(m_mutex); - - if (m_torrents.empty() || m_torrents.front() != t) - { - // this means the torrent was removed right after it was - // added. Abort the checking. - t.reset(); - continue; - } - - // clear the resume data now that it has been used - // (the fast resume data is now parsed and stored in t) - t->resume_data = entry(); - bool up_to_date = t->torrent_ptr->check_fastresume(*t); - - if (up_to_date) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(!m_torrents.empty()); - TORRENT_ASSERT(m_torrents.front() == t); - - t->torrent_ptr->files_checked(t->unfinished_pieces); - m_torrents.pop_front(); - - // we cannot add the torrent if the session is aborted. - if (!m_ses.is_aborted()) - { - m_ses.m_torrents.insert(std::make_pair(t->info_hash, t->torrent_ptr)); - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(torrent_checked_alert( - t->torrent_ptr->get_handle() - , "torrent finished checking")); - } - if (t->torrent_ptr->is_seed() && m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(torrent_finished_alert( - t->torrent_ptr->get_handle() - , "torrent is complete")); - } - - peer_id id; - std::fill(id.begin(), id.end(), 0); - for (std::vector::const_iterator i = t->peers.begin(); - i != t->peers.end(); ++i) - { - t->torrent_ptr->get_policy().peer_from_tracker(*i, id - , peer_info::resume_data, 0); - } - - for (std::vector::const_iterator i = t->banned_peers.begin(); - i != t->banned_peers.end(); ++i) - { - policy::peer* p = t->torrent_ptr->get_policy().peer_from_tracker(*i, id - , peer_info::resume_data, 0); - if (p) p->banned = true; - } - } - else - { - t->torrent_ptr->abort(); - } - t.reset(); - continue; - } - - l.unlock(); - - // move the torrent from - // m_torrents to m_processing - TORRENT_ASSERT(m_torrents.front() == t); - - m_torrents.pop_front(); - m_processing.push_back(t); - if (!processing) - { - processing = t; - processing->processing = true; - t.reset(); - } - } - } - catch (const std::exception& e) - { - // This will happen if the storage fails to initialize - // for example if one of the files has an invalid filename. - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - mutex::scoped_lock l2(m_mutex); - - if (m_ses.m_alerts.should_post(alert::fatal)) - { - m_ses.m_alerts.post_alert( - file_error_alert( - t->torrent_ptr->get_handle() - , e.what())); - } - t->torrent_ptr->abort(); - - TORRENT_ASSERT(!m_torrents.empty()); - m_torrents.pop_front(); - } - catch(...) - { -#ifndef NDEBUG - std::cerr << "error while checking resume data\n"; -#endif - mutex::scoped_lock l(m_mutex); - TORRENT_ASSERT(!m_torrents.empty()); - m_torrents.pop_front(); - TORRENT_ASSERT(false); - } - - if (!processing) continue; - - try - { - TORRENT_ASSERT(processing); - - float finished = false; - float progress = 0.f; - boost::tie(finished, progress) = processing->torrent_ptr->check_files(); - - { - mutex::scoped_lock l2(m_mutex); - - INVARIANT_CHECK; - - processing->progress = progress; - if (processing->abort) - { - TORRENT_ASSERT(!m_processing.empty()); - TORRENT_ASSERT(m_processing.front() == processing); - m_processing.pop_front(); - - // make sure the lock order is correct - l2.unlock(); - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - l2.lock(); - processing->torrent_ptr->abort(); - - processing.reset(); - if (!m_processing.empty()) - { - processing = m_processing.front(); - processing->processing = true; - } - continue; - } - } - if (finished) - { - // lock the session to add the new torrent - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - mutex::scoped_lock l2(m_mutex); - - INVARIANT_CHECK; - - TORRENT_ASSERT(!m_processing.empty()); - TORRENT_ASSERT(m_processing.front() == processing); - - // TODO: factor out the adding of torrents to the session - // and to the checker thread to avoid duplicating the - // check for abortion. - if (!m_ses.is_aborted()) - { - processing->torrent_ptr->files_checked(processing->unfinished_pieces); - m_ses.m_torrents.insert(std::make_pair( - processing->info_hash, processing->torrent_ptr)); - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(torrent_checked_alert( - processing->torrent_ptr->get_handle() - , "torrent finished checking")); - } - if (processing->torrent_ptr->is_seed() - && m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(torrent_finished_alert( - processing->torrent_ptr->get_handle() - , "torrent is complete")); - } - - peer_id id; - std::fill(id.begin(), id.end(), 0); - for (std::vector::const_iterator i = processing->peers.begin(); - i != processing->peers.end(); ++i) - { - processing->torrent_ptr->get_policy().peer_from_tracker(*i, id - , peer_info::resume_data, 0); - } - - for (std::vector::const_iterator i = processing->banned_peers.begin(); - i != processing->banned_peers.end(); ++i) - { - policy::peer* p = processing->torrent_ptr->get_policy().peer_from_tracker(*i, id - , peer_info::resume_data, 0); - if (p) p->banned = true; - } - } - else - { - processing->torrent_ptr->abort(); - } - processing.reset(); - m_processing.pop_front(); - if (!m_processing.empty()) - { - processing = m_processing.front(); - processing->processing = true; - } - } - } - catch(std::exception const& e) - { - // This will happen if the storage fails to initialize - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - mutex::scoped_lock l2(m_mutex); - - if (m_ses.m_alerts.should_post(alert::fatal)) - { - m_ses.m_alerts.post_alert( - file_error_alert( - processing->torrent_ptr->get_handle() - , e.what())); - } - - processing->torrent_ptr->abort(); - - if (!m_processing.empty() - && m_processing.front() == processing) - m_processing.pop_front(); - processing.reset(); - if (!m_processing.empty()) - { - processing = m_processing.front(); - processing->processing = true; - } - } - catch(...) - { -#ifndef NDEBUG - std::cerr << "error while checking files\n"; -#endif - mutex::scoped_lock l(m_mutex); - TORRENT_ASSERT(!m_processing.empty()); - - processing.reset(); - m_processing.pop_front(); - if (!m_processing.empty()) - { - processing = m_processing.front(); - processing->processing = true; - } - - TORRENT_ASSERT(false); - } - } - } - - aux::piece_checker_data* checker_impl::find_torrent(sha1_hash const& info_hash) - { - INVARIANT_CHECK; - for (std::deque >::iterator i - = m_torrents.begin(); i != m_torrents.end(); ++i) - { - if ((*i)->info_hash == info_hash) return i->get(); - } - for (std::deque >::iterator i - = m_processing.begin(); i != m_processing.end(); ++i) - { - if ((*i)->info_hash == info_hash) return i->get(); - } - - return 0; - } - - void checker_impl::remove_torrent(sha1_hash const& info_hash, int options) - { - INVARIANT_CHECK; - for (std::deque >::iterator i - = m_torrents.begin(); i != m_torrents.end(); ++i) - { - if ((*i)->info_hash == info_hash) - { - TORRENT_ASSERT((*i)->processing == false); - if (options & session::delete_files) - (*i)->torrent_ptr->delete_files(); - m_torrents.erase(i); - return; - } - } - for (std::deque >::iterator i - = m_processing.begin(); i != m_processing.end(); ++i) - { - if ((*i)->info_hash == info_hash) - { - TORRENT_ASSERT((*i)->processing == false); - if (options & session::delete_files) - (*i)->torrent_ptr->delete_files(); - m_processing.erase(i); - return; - } - } - - TORRENT_ASSERT(false); - } - -#ifndef NDEBUG - void checker_impl::check_invariant() const - { - for (std::deque >::const_iterator i - = m_torrents.begin(); i != m_torrents.end(); ++i) - { - TORRENT_ASSERT(*i); - TORRENT_ASSERT((*i)->torrent_ptr); - } - for (std::deque >::const_iterator i - = m_processing.begin(); i != m_processing.end(); ++i) - { - TORRENT_ASSERT(*i); - TORRENT_ASSERT((*i)->torrent_ptr); - } - } -#endif +} +namespace aux { struct seed_random_generator { @@ -546,39 +136,60 @@ namespace detail std::pair listen_port_range , fingerprint const& cl_fprint , char const* listen_interface -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , fs::path const& logpath #endif ) - : m_send_buffers(send_buffer_size) - , m_files(40) - , m_strand(m_io_service) + : +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR + m_send_buffers(send_buffer_size), +#endif + m_files(40) + , m_io_service() + , m_disk_thread(m_io_service) , m_half_open(m_io_service) , m_download_channel(m_io_service, peer_connection::download_channel) +#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT + , m_upload_channel(m_io_service, peer_connection::upload_channel, true) +#else , m_upload_channel(m_io_service, peer_connection::upload_channel) +#endif , m_tracker_manager(m_settings, m_tracker_proxy) , m_listen_port_retries(listen_port_range.second - listen_port_range.first) , m_listen_interface(address::from_string(listen_interface), listen_port_range.first) , m_abort(false) + , m_paused(false) , m_max_uploads(8) + , m_allowed_upload_slots(8) , m_max_connections(200) , m_num_unchoked(0) , m_unchoke_time_scaler(0) + , m_auto_manage_time_scaler(0) , m_optimistic_unchoke_time_scaler(0) - , m_disconnect_time_scaler(0) + , m_disconnect_time_scaler(90) + , m_auto_scrape_time_scaler(180) , m_incoming_connection(false) , m_last_tick(time_now()) #ifndef TORRENT_DISABLE_DHT , m_dht_same_port(true) , m_external_udp_port(0) + , m_dht_socket(m_io_service, bind(&session_impl::on_receive_udp, this, _1, _2, _3, _4) + , m_half_open) #endif , m_timer(m_io_service) , m_next_connect_torrent(0) -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , m_logpath(logpath) #endif - , m_checker_impl(*this) +#ifndef TORRENT_DISABLE_GEO_IP + , m_asnum_db(0) + , m_country_db(0) +#endif { + m_tcp_mapping[0] = -1; + m_tcp_mapping[1] = -1; + m_udp_mapping[0] = -1; + m_udp_mapping[1] = -1; #ifdef WIN32 // windows XP has a limit on the number of // simultaneous half-open TCP connections @@ -598,9 +209,14 @@ namespace detail m_bandwidth_manager[peer_connection::download_channel] = &m_download_channel; m_bandwidth_manager[peer_connection::upload_channel] = &m_upload_channel; -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING m_logger = create_log("main_session", listen_port(), false); (*m_logger) << time_now_string() << "\n"; + + (*m_logger) << "sizeof(torrent): " << sizeof(torrent) << "\n"; + (*m_logger) << "sizeof(peer_connection): " << sizeof(peer_connection) << "\n"; + (*m_logger) << "sizeof(bt_peer_connection): " << sizeof(bt_peer_connection) << "\n"; + (*m_logger) << "sizeof(policy::peer): " << sizeof(policy::peer) << "\n"; #endif #ifdef TORRENT_STATS @@ -644,12 +260,119 @@ namespace detail *i = printable[rand() % (sizeof(printable)-1)]; } - m_timer.expires_from_now(seconds(1)); - m_timer.async_wait(m_strand.wrap( - bind(&session_impl::second_tick, this, _1))); + error_code ec; + m_timer.expires_from_now(seconds(1), ec); + m_timer.async_wait( + bind(&session_impl::second_tick, this, _1)); m_thread.reset(new boost::thread(boost::ref(*this))); - m_checker_thread.reset(new boost::thread(boost::ref(m_checker_impl))); + } + +#ifndef TORRENT_DISABLE_GEO_IP + namespace + { + struct free_ptr + { + void* ptr_; + free_ptr(void* p): ptr_(p) {} + ~free_ptr() { free(ptr_); } + }; + } + + char const* session_impl::country_for_ip(address const& a) + { + if (!a.is_v4() || m_country_db == 0) return 0; + return GeoIP_country_code_by_ipnum(m_country_db, a.to_v4().to_ulong()); + } + + int session_impl::as_for_ip(address const& a) + { + if (!a.is_v4() || m_asnum_db == 0) return 0; + char* name = GeoIP_name_by_ipnum(m_asnum_db, a.to_v4().to_ulong()); + if (name == 0) return 0; + free_ptr p(name); + // GeoIP returns the name as AS??? where ? is the AS-number + return atoi(name + 2); + } + + std::string session_impl::as_name_for_ip(address const& a) + { + if (!a.is_v4() || m_asnum_db == 0) return std::string(); + char* name = GeoIP_name_by_ipnum(m_asnum_db, a.to_v4().to_ulong()); + if (name == 0) return std::string(); + free_ptr p(name); + char* tmp = std::strchr(name, ' '); + if (tmp == 0) return std::string(); + return tmp + 1; + } + + std::pair* session_impl::lookup_as(int as) + { + std::map::iterator i = m_as_peak.lower_bound(as); + + if (i == m_as_peak.end() || i->first != as) + { + // we don't have any data for this AS, insert a new entry + i = m_as_peak.insert(i, std::pair(as, 0)); + } + return &(*i); + } + + bool session_impl::load_asnum_db(char const* file) + { + mutex_t::scoped_lock l(m_mutex); + if (m_asnum_db) GeoIP_delete(m_asnum_db); + m_asnum_db = GeoIP_open(file, GEOIP_STANDARD); + return m_asnum_db; + } + + bool session_impl::load_country_db(char const* file) + { + mutex_t::scoped_lock l(m_mutex); + if (m_country_db) GeoIP_delete(m_country_db); + m_country_db = GeoIP_open(file, GEOIP_STANDARD); + return m_country_db; + } + +#endif + + void session_impl::load_state(entry const& ses_state) + { + if (ses_state.type() != entry::dictionary_t) return; + mutex_t::scoped_lock l(m_mutex); +#ifndef TORRENT_DISABLE_GEO_IP + entry const* as_map = ses_state.find_key("AS map"); + if (as_map && as_map->type() == entry::dictionary_t) + { + entry::dictionary_type const& as_peak = as_map->dict(); + for (entry::dictionary_type::const_iterator i = as_peak.begin() + , end(as_peak.end()); i != end; ++i) + { + int as_num = atoi(i->first.c_str()); + if (i->second.type() != entry::int_t || i->second.integer() == 0) continue; + int& peak = m_as_peak[as_num]; + if (peak < i->second.integer()) peak = i->second.integer(); + } + } +#endif + } + + entry session_impl::state() const + { + mutex_t::scoped_lock l(m_mutex); + entry ret; +#ifndef TORRENT_DISABLE_GEO_IP + entry::dictionary_type& as_map = ret["AS map"].dict(); + char buf[10]; + for (std::map::const_iterator i = m_as_peak.begin() + , end(m_as_peak.end()); i != end; ++i) + { + if (i->second == 0) continue; + sprintf(buf, "%05d", i->first); + as_map[buf] = i->second; + } +#endif + return ret; } #ifndef TORRENT_DISABLE_EXTENSIONS @@ -667,6 +390,32 @@ namespace detail } #endif + void session_impl::pause() + { + mutex_t::scoped_lock l(m_mutex); + if (m_paused) return; + m_paused = true; + for (torrent_map::iterator i = m_torrents.begin() + , end(m_torrents.end()); i != end; ++i) + { + torrent& t = *i->second; + if (!t.is_torrent_paused()) t.do_pause(); + } + } + + void session_impl::resume() + { + mutex_t::scoped_lock l(m_mutex); + if (!m_paused) return; + m_paused = false; + for (torrent_map::iterator i = m_torrents.begin() + , end(m_torrents.end()); i != end; ++i) + { + torrent& t = *i->second; + t.do_resume(); + } + } + void session_impl::abort() { mutex_t::scoped_lock l(m_mutex); @@ -676,23 +425,26 @@ namespace detail #endif // abort the main thread m_abort = true; + m_queued_for_checking.clear(); if (m_lsd) m_lsd->close(); if (m_upnp) m_upnp->close(); if (m_natpmp) m_natpmp->close(); #ifndef TORRENT_DISABLE_DHT if (m_dht) m_dht->stop(); + m_dht_socket.close(); #endif - m_timer.cancel(); + error_code ec; + m_timer.cancel(ec); // close the listen sockets for (std::list::iterator i = m_listen_sockets.begin() , end(m_listen_sockets.end()); i != end; ++i) { - i->sock->close(); + i->sock->close(ec); } #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " aborting all torrents\n"; + (*m_logger) << time_now_string() << " aborting all torrents (" << m_torrents.size() << ")\n"; #endif // abort all torrents for (torrent_map::iterator i = m_torrents.begin() @@ -731,10 +483,10 @@ namespace detail #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) boost::shared_ptr tl(new tracker_logger(*this)); m_tracker_loggers.push_back(tl); - m_tracker_manager.queue_request(m_strand, m_half_open, req, login + m_tracker_manager.queue_request(m_io_service, m_half_open, req, login , m_listen_interface.address(), tl); #else - m_tracker_manager.queue_request(m_strand, m_half_open, req, login + m_tracker_manager.queue_request(m_io_service, m_half_open, req, login , m_listen_interface.address()); #endif } @@ -752,7 +504,7 @@ namespace detail #ifndef NDEBUG int conn = m_connections.size(); #endif - (*m_connections.begin())->disconnect(); + (*m_connections.begin())->disconnect("stopping torrent"); TORRENT_ASSERT(conn == int(m_connections.size()) + 1); } @@ -763,12 +515,6 @@ namespace detail m_download_channel.close(); m_upload_channel.close(); - - mutex::scoped_lock l2(m_checker_impl.m_mutex); - // abort the checker thread - m_checker_impl.m_abort = true; - - m_io_service.stop(); } void session_impl::set_port_filter(port_filter const& f) @@ -802,10 +548,22 @@ namespace detail // less than 5 seconds unchoke interval is insane TORRENT_ASSERT(s.unchoke_interval >= 5); + if (m_settings.cache_size != s.cache_size) + m_disk_thread.set_cache_size(s.cache_size); + if (m_settings.cache_expiry != s.cache_expiry) + m_disk_thread.set_cache_size(s.cache_expiry); + // if queuing settings were changed, recalculate + // queued torrents sooner + if ((m_settings.active_downloads != s.active_downloads + || m_settings.active_seeds != s.active_seeds + || m_settings.active_limit != s.active_limit) + && m_auto_manage_time_scaler > 2) + m_auto_manage_time_scaler = 2; m_settings = s; - if (m_settings.connection_speed <= 0) m_settings.connection_speed = 200; - + if (m_settings.connection_speed <= 0) m_settings.connection_speed = 200; + m_files.resize(m_settings.file_pool_size); + if (!s.auto_upload_slots) m_allowed_upload_slots = m_max_uploads; // replace all occurances of '\n' with ' '. std::string::iterator i = m_settings.user_agent.begin(); while ((i = std::find(i, m_settings.user_agent.end(), '\n')) @@ -821,7 +579,7 @@ namespace detail session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep , int retries, bool v6_only) { - asio::error_code ec; + error_code ec; listen_socket_t s; s.sock.reset(new socket_acceptor(m_io_service)); s.sock->open(ep.protocol(), ec); @@ -830,7 +588,7 @@ namespace detail s.sock->bind(ep, ec); while (ec && retries > 0) { - ec = asio::error_code(); + ec = error_code(); TORRENT_ASSERT(!ec); --retries; ep.port(ep.port() + 1); @@ -841,19 +599,14 @@ namespace detail // instead of giving up, try // let the OS pick a port ep.port(0); - ec = asio::error_code(); + ec = error_code(); s.sock->bind(ep, ec); } if (ec) { // not even that worked, give up - if (m_alerts.should_post(alert::fatal)) - { - std::stringstream msg; - msg << "cannot bind to interface '"; - print_endpoint(msg, ep) << "' " << ec.message(); - m_alerts.post_alert(listen_failed_alert(ep, msg.str())); - } + if (m_alerts.should_post()) + m_alerts.post_alert(listen_failed_alert(ep, ec)); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) std::stringstream msg; msg << "cannot bind to interface '"; @@ -866,13 +619,8 @@ namespace detail s.sock->listen(0, ec); if (ec) { - if (m_alerts.should_post(alert::fatal)) - { - std::stringstream msg; - msg << "cannot listen on interface '"; - print_endpoint(msg, ep) << "' " << ec.message(); - m_alerts.post_alert(listen_failed_alert(ep, msg.str())); - } + if (m_alerts.should_post()) + m_alerts.post_alert(listen_failed_alert(ep, ec)); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) std::stringstream msg; msg << "cannot listen on interface '"; @@ -882,12 +630,8 @@ namespace detail return listen_socket_t(); } - if (m_alerts.should_post(alert::fatal)) - { - std::string msg = "listening on interface " - + boost::lexical_cast(ep); - m_alerts.post_alert(listen_succeeded_alert(ep, msg)); - } + if (m_alerts.should_post()) + m_alerts.post_alert(listen_succeeded_alert(ep)); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << "listening on: " << ep @@ -896,7 +640,7 @@ namespace detail return s; } - void session_impl::open_listen_port() throw() + void session_impl::open_listen_port() { // close the open listen sockets m_listen_sockets.clear(); @@ -947,7 +691,7 @@ namespace detail for (std::list::const_iterator i = m_listen_sockets.begin() , end(m_listen_sockets.end()); i != end; ++i) { - asio::error_code ec; + error_code ec; tcp::endpoint ep = i->sock->local_endpoint(ec); if (ec || ep.address().is_v4()) continue; @@ -977,19 +721,55 @@ namespace detail if (!m_listen_sockets.empty()) { - asio::error_code ec; + error_code ec; tcp::endpoint local = m_listen_sockets.front().sock->local_endpoint(ec); if (!ec) { - if (m_natpmp.get()) m_natpmp->set_mappings(local.port(), 0); - if (m_upnp.get()) m_upnp->set_mappings(local.port(), 0); + if (m_natpmp.get()) + { + if (m_tcp_mapping[0] != -1) m_natpmp->delete_mapping(m_tcp_mapping[0]); + m_tcp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp + , local.port(), local.port()); + } + if (m_upnp.get()) + { + if (m_tcp_mapping[1] != -1) m_upnp->delete_mapping(m_tcp_mapping[1]); + m_tcp_mapping[1] = m_upnp->add_mapping(upnp::tcp + , local.port(), local.port()); + } } } } +#ifndef TORRENT_DISABLE_DHT + + void session_impl::on_receive_udp(error_code const& e + , udp::endpoint const& ep, char const* buf, int len) + { + if (e) + { + if (e == asio::error::connection_refused + || e == asio::error::connection_reset + || e == asio::error::connection_aborted) + m_dht->on_unreachable(ep); + + if (m_alerts.should_post()) + m_alerts.post_alert(udp_error_alert(ep, e)); + return; + } + + if (len > 20 && *buf == 'd' && m_dht) + { + // this is probably a dht message + m_dht->on_receive(ep, buf, len); + } + } + +#endif + void session_impl::async_accept(boost::shared_ptr const& listener) { - shared_ptr c(new socket_type); + shared_ptr c(new socket_type(m_io_service)); c->instantiate(m_io_service); listener->async_accept(c->get() , bind(&session_impl::on_incoming_connection, this, c @@ -997,7 +777,7 @@ namespace detail } void session_impl::on_incoming_connection(shared_ptr const& s - , weak_ptr listen_socket, asio::error_code const& e) try + , weak_ptr listen_socket, error_code const& e) { boost::shared_ptr listener = listen_socket.lock(); if (!listener) return; @@ -1007,7 +787,7 @@ namespace detail mutex_t::scoped_lock l(m_mutex); if (m_abort) return; - asio::error_code ec; + error_code ec; if (e) { tcp::endpoint ep = listener->local_endpoint(ec); @@ -1016,7 +796,7 @@ namespace detail + boost::lexical_cast(ep) + "' " + e.message(); (*m_logger) << msg << "\n"; #endif -#ifdef _WIN32 +#ifdef TORRENT_WINDOWS // Windows sometimes generates this error. It seems to be // non-fatal and we have to do another async_accept. if (e.value() == ERROR_SEM_TIMEOUT) @@ -1034,12 +814,8 @@ namespace detail return; } #endif - if (m_alerts.should_post(alert::fatal)) - { - std::string msg = "error accepting connection on '" - + boost::lexical_cast(ep) + "' " + e.message(); - m_alerts.post_alert(listen_failed_alert(ep, msg)); - } + if (m_alerts.should_post()) + m_alerts.post_alert(listen_failed_alert(ep, e)); return; } async_accept(listener); @@ -1057,7 +833,7 @@ namespace detail } #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << endp << " <== INCOMING CONNECTION\n"; + (*m_logger) << time_now_string() << " <== INCOMING CONNECTION " << endp << "\n"; #endif // local addresses do not count, since it's likely @@ -1072,11 +848,8 @@ namespace detail #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << "filtered blocked ip\n"; #endif - if (m_alerts.should_post(alert::info)) - { - m_alerts.post_alert(peer_blocked_alert(endp.address() - , "incoming connection blocked by IP filter")); - } + if (m_alerts.should_post()) + m_alerts.post_alert(peer_blocked_alert(endp.address())); return; } @@ -1125,66 +898,40 @@ namespace detail c->m_in_constructor = false; #endif - m_connections.insert(c); - } - catch (std::exception& exc) - { -#ifndef NDEBUG - std::string err = exc.what(); -#endif - }; - - void session_impl::connection_failed(boost::intrusive_ptr const& peer - , tcp::endpoint const& a, char const* message) -#ifndef NDEBUG - try -#endif - { - mutex_t::scoped_lock l(m_mutex); - -// too expensive -// INVARIANT_CHECK; - - connection_map::iterator p = m_connections.find(peer); - - // the connection may have been disconnected in the receive or send phase - if (p == m_connections.end()) return; - if (m_alerts.should_post(alert::debug)) + if (!c->is_disconnecting()) { - m_alerts.post_alert( - peer_error_alert( - a - , (*p)->pid() - , message)); + m_connections.insert(c); + c->start(); } - -#if defined(TORRENT_VERBOSE_LOGGING) - (*(*p)->m_logger) << "*** CONNECTION FAILED " << message << "\n"; -#endif - (*p)->set_failed(); - (*p)->disconnect(); } -#ifndef NDEBUG - catch (...) - { - TORRENT_ASSERT(false); - }; -#endif - - void session_impl::close_connection(boost::intrusive_ptr const& p) + void session_impl::close_connection(peer_connection const* p + , char const* message) { mutex_t::scoped_lock l(m_mutex); // too expensive // INVARIANT_CHECK; +#ifndef NDEBUG +// for (aux::session_impl::torrent_map::const_iterator i = m_torrents.begin() +// , end(m_torrents.end()); i != end; ++i) +// TORRENT_ASSERT(!i->second->has_peer((peer_connection*)p)); +#endif + +#if defined(TORRENT_LOGGING) + (*m_logger) << time_now_string() << " CLOSING CONNECTION " + << p->remote() << " : " << message << "\n"; +#endif + TORRENT_ASSERT(p->is_disconnecting()); - connection_map::iterator i = m_connections.find(p); - if (i != m_connections.end()) - { - if (!(*i)->is_choked()) --m_num_unchoked; - m_connections.erase(i); - } + + if (!p->is_choked()) --m_num_unchoked; +// connection_map::iterator i = std::lower_bound(m_connections.begin(), m_connections.end() +// , p, bind(&boost::intrusive_ptr::get, _1) < p); +// if (i->get() != p) i == m_connections.end(); + connection_map::iterator i = std::find_if(m_connections.begin(), m_connections.end() + , bind(&boost::intrusive_ptr::get, _1) == p); + if (i != m_connections.end()) m_connections.erase(i); } void session_impl::set_peer_id(peer_id const& id) @@ -1199,7 +946,23 @@ namespace detail m_key = key; } - void session_impl::second_tick(asio::error_code const& e) try + int session_impl::next_port() + { + std::pair const& out_ports = m_settings.outgoing_ports; + if (m_next_port < out_ports.first || m_next_port > out_ports.second) + m_next_port = out_ports.first; + + int port = m_next_port; + ++m_next_port; + if (m_next_port > out_ports.second) m_next_port = out_ports.first; +#if defined TORRENT_LOGGING + (*m_logger) << time_now_string() << " *** BINDING OUTGOING CONNECTION [ " + "port: " << port << " ]\n"; +#endif + return port; + } + + void session_impl::second_tick(error_code const& e) { session_impl::mutex_t::scoped_lock l(m_mutex); @@ -1210,19 +973,20 @@ namespace detail if (e) { -#if defined(TORRENT_LOGGING) +#if defined TORRENT_LOGGING (*m_logger) << "*** SECOND TIMER FAILED " << e.message() << "\n"; #endif - abort(); + ::abort(); return; } float tick_interval = total_microseconds(time_now() - m_last_tick) / 1000000.f; m_last_tick = time_now(); - m_timer.expires_from_now(seconds(1)); - m_timer.async_wait(m_strand.wrap( - bind(&session_impl::second_tick, this, _1))); + error_code ec; + m_timer.expires_from_now(seconds(1), ec); + m_timer.async_wait( + bind(&session_impl::second_tick, this, _1)); #ifdef TORRENT_STATS ++m_second_counter; @@ -1259,7 +1023,121 @@ namespace detail << std::endl; #endif - + // -------------------------------------------------------------- + // check for incoming connections that might have timed out + // -------------------------------------------------------------- + + for (connection_map::iterator i = m_connections.begin(); + i != m_connections.end();) + { + peer_connection* p = (*i).get(); + ++i; + // ignore connections that already have a torrent, since they + // are ticket through the torrents' second_ticket + if (!p->associated_torrent().expired()) continue; + if (m_last_tick - p->connected_time() > seconds(m_settings.peer_connect_timeout)) + p->disconnect("timeout: incoming connection"); + } + + // -------------------------------------------------------------- + // second_tick every torrent + // -------------------------------------------------------------- + + int congested_torrents = 0; + int uncongested_torrents = 0; + + // count the number of seeding torrents vs. downloading + // torrents we are running + int num_seeds = 0; + int num_downloads = 0; + + // count the number of peers of downloading torrents + int num_downloads_peers = 0; + + torrent_map::iterator least_recently_scraped = m_torrents.begin(); + int num_paused_auto_managed = 0; + + // check each torrent for tracker updates + // TODO: do this in a timer-event in each torrent instead + for (torrent_map::iterator i = m_torrents.begin(); + i != m_torrents.end();) + { + torrent& t = *i->second; + TORRENT_ASSERT(!t.is_aborted()); + if (t.bandwidth_queue_size(peer_connection::upload_channel)) + ++congested_torrents; + else + ++uncongested_torrents; + + if (t.is_auto_managed() && t.is_paused() && !t.has_error()) + { + ++num_paused_auto_managed; + if (!least_recently_scraped->second->is_auto_managed() + || !least_recently_scraped->second->is_paused() + || least_recently_scraped->second->last_scrape() > t.last_scrape()) + { + least_recently_scraped = i; + } + } + + if (t.is_finished()) + { + ++num_seeds; + } + else + { + ++num_downloads; + num_downloads_peers += t.num_peers(); + } + + if (t.should_request()) + { + tracker_request req = t.generate_tracker_request(); + req.listen_port = 0; + if (!m_listen_sockets.empty()) + req.listen_port = m_listen_sockets.front().external_port; + req.key = m_key; + m_tracker_manager.queue_request(m_io_service, m_half_open, req + , t.tracker_login(), m_listen_interface.address(), i->second); + + if (m_alerts.should_post()) + { + m_alerts.post_alert( + tracker_announce_alert(t.get_handle(), req.url)); + } + } + + t.second_tick(m_stat, tick_interval); + ++i; + } + + // drain the IP overhead from the bandwidth limiters + m_download_channel.drain(m_stat.download_ip_overhead()); + m_upload_channel.drain(m_stat.upload_ip_overhead()); + + m_stat.second_tick(tick_interval); + + // -------------------------------------------------------------- + // scrape paused torrents that are auto managed + // -------------------------------------------------------------- + --m_auto_scrape_time_scaler; + if (m_auto_scrape_time_scaler <= 0) + { + m_auto_scrape_time_scaler = m_settings.auto_scrape_interval + / (std::max)(1, num_paused_auto_managed); + if (m_auto_scrape_time_scaler < m_settings.auto_scrape_min_interval) + m_auto_scrape_time_scaler = m_settings.auto_scrape_min_interval; + + if (least_recently_scraped != m_torrents.end()) + { + least_recently_scraped->second->scrape_tracker(); + } + } + + // -------------------------------------------------------------- + // connect new peers + // -------------------------------------------------------------- + // let torrents connect to peers if they want to // if there are any torrents and any free slots @@ -1268,13 +1146,17 @@ namespace detail // round robin fashion, so that every torrent is // equallt likely to connect to a peer + int free_slots = m_half_open.free_slots(); if (!m_torrents.empty() - && m_half_open.free_slots() + && free_slots > -m_half_open.limit() && num_connections() < m_max_connections) { // this is the maximum number of connections we will // attempt this tick int max_connections = m_settings.connection_speed; + int average_peers = 0; + if (num_downloads > 0) + average_peers = num_downloads_peers / num_downloads; torrent_map::iterator i = m_torrents.begin(); if (m_next_connect_torrent < int(m_torrents.size())) @@ -1288,11 +1170,27 @@ namespace detail torrent& t = *i->second; if (t.want_more_peers()) { + int connect_points = 100; + // have a bias against torrents with more peers + // than average + if (!t.is_seed() && t.num_peers() > average_peers) + connect_points /= 2; + // if this is a seed and there is a torrent that + // is downloading, lower the rate at which this + // torrent gets connections. + // dividing by num_seeds will have the effect + // that all seed will get as many connections + // together, as a single downloading torrent. + if (t.is_seed() && num_downloads > 0) + connect_points /= num_seeds + 1; + if (connect_points <= 0) connect_points = 1; + t.give_connect_points(connect_points); try { if (t.try_connect_peer()) { --max_connections; + --free_slots; steps_since_last_connect = 0; } } @@ -1314,11 +1212,11 @@ namespace detail i = m_torrents.begin(); m_next_connect_torrent = 0; } - // if we have gone one whole loop without + // if we have gone two whole loops without // handing out a single connection, break - if (steps_since_last_connect > num_torrents) break; + if (steps_since_last_connect > num_torrents * 2) break; // if there are no more free connection slots, abort - if (m_half_open.free_slots() == 0) break; + if (free_slots <= -m_half_open.limit()) break; // if we should not make any more connections // attempts this tick, abort if (max_connections == 0) break; @@ -1327,74 +1225,16 @@ namespace detail } } - // do the second_tick() on each connection - // this will update their statistics (download and upload speeds) - // also purge sockets that have timed out - // and keep sockets open by keeping them alive. - for (connection_map::iterator i = m_connections.begin(); - i != m_connections.end();) + // -------------------------------------------------------------- + // auto managed torrent + // -------------------------------------------------------------- + m_auto_manage_time_scaler--; + if (m_auto_manage_time_scaler <= 0) { - // we need to do like this because j->second->disconnect() will - // erase the connection from the map we're iterating - connection_map::iterator j = i; - ++i; - // if this socket has timed out - // close it. - peer_connection& c = *j->get(); - if (c.has_timed_out()) - { - if (m_alerts.should_post(alert::debug)) - { - m_alerts.post_alert( - peer_error_alert( - c.remote() - , c.pid() - , "connection timed out")); - } -#if defined(TORRENT_VERBOSE_LOGGING) - (*c.m_logger) << "*** CONNECTION TIMED OUT\n"; -#endif - - c.set_failed(); - c.disconnect(); - continue; - } - - c.keep_alive(); + m_auto_manage_time_scaler = settings().auto_manage_interval; + recalculate_auto_managed_torrents(); } - // check each torrent for tracker updates - // TODO: do this in a timer-event in each torrent instead - for (torrent_map::iterator i = m_torrents.begin(); - i != m_torrents.end();) - { - torrent& t = *i->second; - TORRENT_ASSERT(!t.is_aborted()); - if (t.should_request()) - { - tracker_request req = t.generate_tracker_request(); - req.listen_port = 0; - if (!m_listen_sockets.empty()) - req.listen_port = m_listen_sockets.front().external_port; - req.key = m_key; - m_tracker_manager.queue_request(m_strand, m_half_open, req - , t.tracker_login(), m_listen_interface.address(), i->second); - - if (m_alerts.should_post(alert::info)) - { - m_alerts.post_alert( - tracker_announce_alert( - t.get_handle(), "tracker announce")); - } - } - - // second_tick() will set the used upload quota - t.second_tick(m_stat, tick_interval); - ++i; - } - - m_stat.second_tick(tick_interval); - // -------------------------------------------------------------- // unchoke set and optimistic unchoke calculations // -------------------------------------------------------------- @@ -1402,154 +1242,8 @@ namespace detail if (m_unchoke_time_scaler <= 0 && !m_connections.empty()) { m_unchoke_time_scaler = settings().unchoke_interval; - - std::vector peers; - for (connection_map::iterator i = m_connections.begin() - , end(m_connections.end()); i != end; ++i) - { - peer_connection* p = i->get(); - torrent* t = p->associated_torrent().lock().get(); - if (!p->peer_info_struct() - || t == 0 - || !p->is_peer_interested() - || p->is_disconnecting() - || p->is_connecting() - || (p->share_diff() < -free_upload_amount - && !t->is_seed())) - { - if (!(*i)->is_choked() && t) - { - policy::peer* pi = p->peer_info_struct(); - if (pi && pi->optimistically_unchoked) - { - pi->optimistically_unchoked = false; - // force a new optimistic unchoke - m_optimistic_unchoke_time_scaler = 0; - } - t->choke_peer(*(*i)); - } - continue; - } - peers.push_back(i->get()); - } - - // sort the peers that are eligible for unchoke by download rate and secondary - // by total upload. The reason for this is, if all torrents are being seeded, - // the download rate will be 0, and the peers we have sent the least to should - // be unchoked - std::sort(peers.begin(), peers.end() - , bind(&stat::total_payload_upload, bind(&peer_connection::statistics, _1)) - < bind(&stat::total_payload_upload, bind(&peer_connection::statistics, _2))); - - std::stable_sort(peers.begin(), peers.end() - , bind(&stat::download_payload_rate, bind(&peer_connection::statistics, _1)) - > bind(&stat::download_payload_rate, bind(&peer_connection::statistics, _2))); - - // reserve one upload slot for optimistic unchokes - int unchoke_set_size = m_max_uploads - 1; - - m_num_unchoked = 0; - // go through all the peers and unchoke the first ones and choke - // all the other ones. - for (std::vector::iterator i = peers.begin() - , end(peers.end()); i != end; ++i) - { - peer_connection* p = *i; - TORRENT_ASSERT(p); - torrent* t = p->associated_torrent().lock().get(); - TORRENT_ASSERT(t); - if (unchoke_set_size > 0) - { - if (p->is_choked()) - { - if (!t->unchoke_peer(*p)) - continue; - } - - --unchoke_set_size; - ++m_num_unchoked; - - TORRENT_ASSERT(p->peer_info_struct()); - if (p->peer_info_struct()->optimistically_unchoked) - { - // force a new optimistic unchoke - m_optimistic_unchoke_time_scaler = 0; - p->peer_info_struct()->optimistically_unchoked = false; - } - } - else - { - TORRENT_ASSERT(p->peer_info_struct()); - if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked) - t->choke_peer(*p); - if (!p->is_choked()) - ++m_num_unchoked; - } - } - - m_optimistic_unchoke_time_scaler--; - if (m_optimistic_unchoke_time_scaler <= 0) - { - m_optimistic_unchoke_time_scaler - = settings().optimistic_unchoke_multiplier; - - // find the peer that has been waiting the longest to be optimistically - // unchoked - connection_map::iterator current_optimistic_unchoke = m_connections.end(); - connection_map::iterator optimistic_unchoke_candidate = m_connections.end(); - ptime last_unchoke = max_time(); - - for (connection_map::iterator i = m_connections.begin() - , end(m_connections.end()); i != end; ++i) - { - peer_connection* p = i->get(); - TORRENT_ASSERT(p); - policy::peer* pi = p->peer_info_struct(); - if (!pi) continue; - torrent* t = p->associated_torrent().lock().get(); - if (!t) continue; - - if (pi->optimistically_unchoked) - { - TORRENT_ASSERT(!p->is_choked()); - TORRENT_ASSERT(current_optimistic_unchoke == m_connections.end()); - current_optimistic_unchoke = i; - } - - if (pi->last_optimistically_unchoked < last_unchoke - && !p->is_connecting() - && !p->is_disconnecting() - && p->is_peer_interested() - && t->free_upload_slots() - && p->is_choked()) - { - last_unchoke = pi->last_optimistically_unchoked; - optimistic_unchoke_candidate = i; - } - } - - if (optimistic_unchoke_candidate != m_connections.end() - && optimistic_unchoke_candidate != current_optimistic_unchoke) - { - if (current_optimistic_unchoke != m_connections.end()) - { - torrent* t = (*current_optimistic_unchoke)->associated_torrent().lock().get(); - TORRENT_ASSERT(t); - (*current_optimistic_unchoke)->peer_info_struct()->optimistically_unchoked = false; - t->choke_peer(*current_optimistic_unchoke->get()); - } - else - { - ++m_num_unchoked; - } - - torrent* t = (*optimistic_unchoke_candidate)->associated_torrent().lock().get(); - TORRENT_ASSERT(t); - bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->get()); - TORRENT_ASSERT(ret); - (*optimistic_unchoke_candidate)->peer_info_struct()->optimistically_unchoked = true; - } - } + recalculate_unchoke_slots(congested_torrents + , uncongested_torrents); } // -------------------------------------------------------------- @@ -1558,28 +1252,337 @@ namespace detail --m_disconnect_time_scaler; if (m_disconnect_time_scaler <= 0) { - m_disconnect_time_scaler = 60; + m_disconnect_time_scaler = 90; - // every 60 seconds, disconnect the worst peer + // every 90 seconds, disconnect the worst peers // if we have reached the connection limit - if (num_connections() >= max_connections() && !m_torrents.empty()) + if (num_connections() >= max_connections() * m_settings.peer_turnover_cutoff + && !m_torrents.empty()) { torrent_map::iterator i = std::max_element(m_torrents.begin(), m_torrents.end() , bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _1)) < bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _2))); TORRENT_ASSERT(i != m_torrents.end()); - i->second->get_policy().disconnect_one_peer(); + int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers() + * m_settings.peer_turnover), 1) + , i->second->get_policy().num_connect_candidates()); + i->second->disconnect_peers(peers_to_disconnect); + } + else + { + // if we haven't reached the global max. see if any torrent + // has reached its local limit + for (torrent_map::iterator i = m_torrents.begin() + , end(m_torrents.end()); i != end; ++i) + { + boost::shared_ptr t = i->second; + if (t->num_peers() < t->max_connections() * m_settings.peer_turnover_cutoff) + continue; + + int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers() + * m_settings.peer_turnover), 1) + , i->second->get_policy().num_connect_candidates()); + t->disconnect_peers(peers_to_disconnect); + } } } } - catch (std::exception& exc) + + namespace { -#ifndef NDEBUG - std::cerr << exc.what() << std::endl; - TORRENT_ASSERT(false); + bool is_active(torrent* t, session_settings const& s) + { + return !(s.dont_count_slow_torrents + && t->statistics().upload_payload_rate() == 0.f + && t->statistics().download_payload_rate() == 0.f); + } + } + + void session_impl::recalculate_auto_managed_torrents() + { + // these vectors are filled with auto managed torrents + std::vector downloaders; + downloaders.reserve(m_torrents.size()); + std::vector seeds; + seeds.reserve(m_torrents.size()); + + // these counters are set to the number of torrents + // of each kind we're allowed to have active + int num_downloaders = settings().active_downloads; + int num_seeds = settings().active_seeds; + int hard_limit = settings().active_limit; + + if (num_downloaders == -1) + num_downloaders = (std::numeric_limits::max)(); + if (num_seeds == -1) + num_seeds = (std::numeric_limits::max)(); + if (hard_limit == -1) + hard_limit = (std::numeric_limits::max)(); + + for (torrent_map::iterator i = m_torrents.begin() + , end(m_torrents.end()); i != end; ++i) + { + torrent* t = i->second.get(); + TORRENT_ASSERT(t); + if (t->is_auto_managed() && !t->has_error()) + { + // this torrent is auto managed, add it to + // the list (depending on if it's a seed or not) + if (t->is_finished()) + seeds.push_back(t); + else + downloaders.push_back(t); + } + else if (!t->is_paused()) + { + --hard_limit; + if (is_active(t, settings())) + { + // this is not an auto managed torrent, + // if it's running and active, decrease the + // counters. + --num_downloaders; + --num_seeds; + } + } + } + + bool handled_by_extension = false; + +#ifndef TORRENT_DISABLE_EXTENSIONS + // TODO: allow extensions to sort torrents for queuing #endif - }; // msvc 7.1 seems to require this + + if (!handled_by_extension) + { + std::sort(downloaders.begin(), downloaders.end() + , bind(&torrent::sequence_number, _1) < bind(&torrent::sequence_number, _2)); + + std::sort(seeds.begin(), seeds.end() + , bind(&torrent::seed_rank, _1, boost::ref(m_settings)) + > bind(&torrent::seed_rank, _2, boost::ref(m_settings))); + } + + for (std::vector::iterator i = downloaders.begin() + , end(downloaders.end()); i != end; ++i) + { + torrent* t = *i; + if (!t->is_paused() && !is_active(t, settings()) && hard_limit > 0) + { + --hard_limit; + continue; + } + + if (num_downloaders > 0 && hard_limit > 0) + { + --hard_limit; + if (t->state() != torrent_status::queued_for_checking + && t->state() != torrent_status::checking_files) + { + --num_downloaders; + if (t->is_paused()) t->resume(); + } + } + else + { + if (!t->is_paused()) t->pause(); + } + } + + for (std::vector::iterator i = seeds.begin() + , end(seeds.end()); i != end; ++i) + { + torrent* t = *i; + if (!t->is_paused() && !is_active(t, settings()) && hard_limit > 0) + { + --hard_limit; + continue; + } + + if (num_seeds > 0 && hard_limit > 0) + { + --hard_limit; + --num_seeds; + if (t->is_paused()) t->resume(); + } + else + { + if (!t->is_paused()) t->pause(); + } + } + } + + void session_impl::recalculate_unchoke_slots(int congested_torrents + , int uncongested_torrents) + { + std::vector peers; + for (connection_map::iterator i = m_connections.begin() + , end(m_connections.end()); i != end; ++i) + { + peer_connection* p = i->get(); + torrent* t = p->associated_torrent().lock().get(); + if (!p->peer_info_struct() + || t == 0 + || !p->is_peer_interested() + || p->is_disconnecting() + || p->is_connecting() + || (p->share_diff() < -free_upload_amount + && !t->is_seed())) + { + if (!(*i)->is_choked() && t) + { + policy::peer* pi = p->peer_info_struct(); + if (pi && pi->optimistically_unchoked) + { + pi->optimistically_unchoked = false; + // force a new optimistic unchoke + m_optimistic_unchoke_time_scaler = 0; + } + t->choke_peer(*(*i)); + } + continue; + } + peers.push_back(i->get()); + } + + // sorts the peers that are eligible for unchoke by download rate and secondary + // by total upload. The reason for this is, if all torrents are being seeded, + // the download rate will be 0, and the peers we have sent the least to should + // be unchoked + std::sort(peers.begin(), peers.end() + , bind(&peer_connection::unchoke_compare, _1, _2)); + + std::for_each(m_connections.begin(), m_connections.end() + , bind(&peer_connection::reset_choke_counters, _1)); + + // auto unchoke + int upload_limit = m_bandwidth_manager[peer_connection::upload_channel]->throttle(); + if (m_settings.auto_upload_slots && upload_limit != bandwidth_limit::inf) + { + // if our current upload rate is less than 90% of our + // limit AND most torrents are not "congested", i.e. + // they are not holding back because of a per-torrent + // limit + if (m_stat.upload_rate() < upload_limit * 0.9f + && m_allowed_upload_slots <= m_num_unchoked + 1 + && congested_torrents < uncongested_torrents) + { + ++m_allowed_upload_slots; + } + else if (m_upload_channel.queue_size() > 1 + && m_allowed_upload_slots > m_max_uploads) + { + --m_allowed_upload_slots; + } + } + + // reserve one upload slot for optimistic unchokes + int unchoke_set_size = m_allowed_upload_slots - 1; + + m_num_unchoked = 0; + // go through all the peers and unchoke the first ones and choke + // all the other ones. + for (std::vector::iterator i = peers.begin() + , end(peers.end()); i != end; ++i) + { + peer_connection* p = *i; + TORRENT_ASSERT(p); + torrent* t = p->associated_torrent().lock().get(); + TORRENT_ASSERT(t); + if (unchoke_set_size > 0) + { + if (p->is_choked()) + { + if (!t->unchoke_peer(*p)) + continue; + } + + --unchoke_set_size; + ++m_num_unchoked; + + TORRENT_ASSERT(p->peer_info_struct()); + if (p->peer_info_struct()->optimistically_unchoked) + { + // force a new optimistic unchoke + m_optimistic_unchoke_time_scaler = 0; + p->peer_info_struct()->optimistically_unchoked = false; + } + } + else + { + TORRENT_ASSERT(p->peer_info_struct()); + if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked) + t->choke_peer(*p); + if (!p->is_choked()) + ++m_num_unchoked; + } + } + + m_optimistic_unchoke_time_scaler--; + if (m_optimistic_unchoke_time_scaler <= 0) + { + m_optimistic_unchoke_time_scaler + = settings().optimistic_unchoke_multiplier; + + // find the peer that has been waiting the longest to be optimistically + // unchoked + connection_map::iterator current_optimistic_unchoke = m_connections.end(); + connection_map::iterator optimistic_unchoke_candidate = m_connections.end(); + ptime last_unchoke = max_time(); + + for (connection_map::iterator i = m_connections.begin() + , end(m_connections.end()); i != end; ++i) + { + peer_connection* p = i->get(); + TORRENT_ASSERT(p); + policy::peer* pi = p->peer_info_struct(); + if (!pi) continue; + torrent* t = p->associated_torrent().lock().get(); + if (!t) continue; + + if (pi->optimistically_unchoked) + { + TORRENT_ASSERT(!p->is_choked()); + TORRENT_ASSERT(current_optimistic_unchoke == m_connections.end()); + current_optimistic_unchoke = i; + } + + if (pi->last_optimistically_unchoked < last_unchoke + && !p->is_connecting() + && !p->is_disconnecting() + && p->is_peer_interested() + && t->free_upload_slots() + && p->is_choked()) + { + last_unchoke = pi->last_optimistically_unchoked; + optimistic_unchoke_candidate = i; + } + } + + if (optimistic_unchoke_candidate != m_connections.end() + && optimistic_unchoke_candidate != current_optimistic_unchoke) + { + if (current_optimistic_unchoke != m_connections.end()) + { + torrent* t = (*current_optimistic_unchoke)->associated_torrent().lock().get(); + TORRENT_ASSERT(t); + (*current_optimistic_unchoke)->peer_info_struct()->optimistically_unchoked = false; + t->choke_peer(*current_optimistic_unchoke->get()); + } + else + { + ++m_num_unchoked; + } + + torrent* t = (*optimistic_unchoke_candidate)->associated_torrent().lock().get(); + TORRENT_ASSERT(t); + bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->get()); + TORRENT_ASSERT(ret); + (*optimistic_unchoke_candidate)->peer_info_struct()->optimistically_unchoked = true; + } + } + } void session_impl::operator()() { @@ -1594,10 +1597,13 @@ namespace detail do { +#ifndef BOOST_NO_EXCEPTIONS try { +#endif m_io_service.run(); TORRENT_ASSERT(m_abort == true); +#ifndef BOOST_NO_EXCEPTIONS } catch (std::exception& e) { @@ -1607,32 +1613,16 @@ namespace detail #endif TORRENT_ASSERT(false); } +#endif } while (!m_abort); - ptime end = time_now() + seconds(m_settings.stop_tracker_timeout); - while (time_now() < end && !m_tracker_manager.empty()) - { - m_io_service.reset(); - m_io_service.poll(); - // sleep 200 milliseconds - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - boost::int64_t nsec = xt.nsec + 200 * 1000000; - if (nsec > 1000000000) - { - nsec -= 1000000000; - xt.sec += 1; - } - xt.nsec = boost::xtime::xtime_nsec_t(nsec); - boost::thread::sleep(xt); - } - #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << time_now_string() << " locking mutex\n"; #endif - session_impl::mutex_t::scoped_lock l(m_mutex); + session_impl::mutex_t::scoped_lock l(m_mutex); +/* #ifndef NDEBUG for (torrent_map::iterator i = m_torrents.begin(); i != m_torrents.end(); ++i) @@ -1640,7 +1630,7 @@ namespace detail TORRENT_ASSERT(i->second->num_peers() == 0); } #endif - +*/ #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << time_now_string() << " cleaning up torrents\n"; #endif @@ -1669,7 +1659,7 @@ namespace detail return boost::weak_ptr(); } -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING boost::shared_ptr session_impl::create_log(std::string const& name , int instance, bool append) { @@ -1681,102 +1671,109 @@ namespace detail std::vector session_impl::get_torrents() { mutex_t::scoped_lock l(m_mutex); - mutex::scoped_lock l2(m_checker_impl.m_mutex); std::vector ret; - for (std::deque >::iterator i - = m_checker_impl.m_torrents.begin() - , end(m_checker_impl.m_torrents.end()); i != end; ++i) - { - if ((*i)->abort) continue; - ret.push_back(torrent_handle(this, &m_checker_impl - , (*i)->info_hash)); - } - - for (std::deque >::iterator i - = m_checker_impl.m_processing.begin() - , end(m_checker_impl.m_processing.end()); i != end; ++i) - { - if ((*i)->abort) continue; - ret.push_back(torrent_handle(this, &m_checker_impl - , (*i)->info_hash)); - } for (session_impl::torrent_map::iterator i = m_torrents.begin(), end(m_torrents.end()); i != end; ++i) { if (i->second->is_aborted()) continue; - ret.push_back(torrent_handle(this, &m_checker_impl - , i->first)); + ret.push_back(torrent_handle(i->second)); } return ret; } torrent_handle session_impl::find_torrent_handle(sha1_hash const& info_hash) { - return torrent_handle(this, &m_checker_impl, info_hash); + return torrent_handle(find_torrent(info_hash)); } - torrent_handle session_impl::add_torrent( - boost::intrusive_ptr ti - , fs::path const& save_path - , entry const& resume_data - , storage_mode_t storage_mode - , storage_constructor_type sc - , bool paused - , void* userdata) + torrent_handle session_impl::add_torrent(add_torrent_params const& params) { - TORRENT_ASSERT(!save_path.empty()); + TORRENT_ASSERT(!params.save_path.empty()); - if (ti->begin_files() == ti->end_files()) + if (params.ti && params.ti->files().num_files() == 0) + { +#ifndef BOOST_NO_EXCEPTIONS throw std::runtime_error("no files in torrent"); +#else + return torrent_handle(); +#endif + } // lock the session and the checker thread (the order is important!) mutex_t::scoped_lock l(m_mutex); - mutex::scoped_lock l2(m_checker_impl.m_mutex); // INVARIANT_CHECK; if (is_aborted()) + { +#ifndef BOOST_NO_EXCEPTIONS throw std::runtime_error("session is closing"); +#else + return torrent_handle(); +#endif + } - // is the torrent already active? - if (!find_torrent(ti->info_hash()).expired()) - throw duplicate_torrent(); + // figure out the info hash of the torrent + sha1_hash const* ih = 0; + if (params.ti) ih = ¶ms.ti->info_hash(); + else ih = ¶ms.info_hash; - // is the torrent currently being checked? - if (m_checker_impl.find_torrent(ti->info_hash())) + // is the torrent already active? + boost::shared_ptr torrent_ptr = find_torrent(*ih).lock(); + if (torrent_ptr) + { + if (!params.duplicate_is_error) + return torrent_handle(torrent_ptr); + +#ifndef BOOST_NO_EXCEPTIONS throw duplicate_torrent(); +#else + return torrent_handle(); +#endif + } + + int queue_pos = 0; + for (torrent_map::const_iterator i = m_torrents.begin() + , end(m_torrents.end()); i != end; ++i) + { + int pos = i->second->queue_position(); + if (pos >= queue_pos) queue_pos = pos + 1; + } // create the torrent and the data associated with // the checker thread and store it before starting // the thread - boost::shared_ptr torrent_ptr( - new torrent(*this, m_checker_impl, ti, save_path - , m_listen_interface, storage_mode, 16 * 1024 - , sc, paused)); + if (params.ti) + { + torrent_ptr.reset(new torrent(*this, params.ti, params.save_path + , m_listen_interface, params.storage_mode, 16 * 1024 + , params.storage, params.paused, params.resume_data + , queue_pos, params.auto_managed)); + } + else + { + torrent_ptr.reset(new torrent(*this, params.tracker_url, *ih, params.name + , params.save_path, m_listen_interface, params.storage_mode, 16 * 1024 + , params.storage, params.paused, params.resume_data + , queue_pos, params.auto_managed)); + } torrent_ptr->start(); #ifndef TORRENT_DISABLE_EXTENSIONS for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) { - boost::shared_ptr tp((*i)(torrent_ptr.get(), userdata)); + boost::shared_ptr tp((*i)(torrent_ptr.get(), params.userdata)); if (tp) torrent_ptr->add_extension(tp); } #endif - boost::shared_ptr d( - new aux::piece_checker_data); - d->torrent_ptr = torrent_ptr; - d->save_path = save_path; - d->info_hash = ti->info_hash(); - d->resume_data = resume_data; - #ifndef TORRENT_DISABLE_DHT - if (m_dht) + if (m_dht && params.ti) { - torrent_info::nodes_t const& nodes = ti->nodes(); + torrent_info::nodes_t const& nodes = params.ti->nodes(); std::for_each(nodes.begin(), nodes.end(), bind( (void(dht::dht_tracker::*)(std::pair const&)) &dht::dht_tracker::add_node @@ -1784,86 +1781,56 @@ namespace detail } #endif - // add the torrent to the queue to be checked - m_checker_impl.m_torrents.push_back(d); - // and notify the thread that it got another - // job in its queue - m_checker_impl.m_cond.notify_one(); + m_torrents.insert(std::make_pair(*ih, torrent_ptr)); - return torrent_handle(this, &m_checker_impl, ti->info_hash()); + // if this is an auto managed torrent, force a recalculation + // of which torrents to have active + if (params.auto_managed && m_auto_manage_time_scaler > 2) + m_auto_manage_time_scaler = 2; + + return torrent_handle(torrent_ptr); } - torrent_handle session_impl::add_torrent( - char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , fs::path const& save_path - , entry const& - , storage_mode_t storage_mode - , storage_constructor_type sc - , bool paused - , void* userdata) + void session_impl::check_torrent(boost::shared_ptr const& t) { - - // TODO: support resume data in this case - TORRENT_ASSERT(!save_path.empty()); + if (m_abort) return; + if (m_queued_for_checking.empty()) t->start_checking(); + m_queued_for_checking.push_back(t); + } + + void session_impl::done_checking(boost::shared_ptr const& t) + { + if (m_queued_for_checking.empty()) return; + check_queue_t::iterator next_check = m_queued_for_checking.begin(); + check_queue_t::iterator done = m_queued_for_checking.end(); + for (check_queue_t::iterator i = m_queued_for_checking.begin() + , end(m_queued_for_checking.end()); i != end; ++i) { - // lock the checker_thread - mutex::scoped_lock l(m_checker_impl.m_mutex); - - // is the torrent currently being checked? - if (m_checker_impl.find_torrent(info_hash)) - throw duplicate_torrent(); + if (*i == t) done = i; + if (next_check == done || (*next_check)->queue_position() > (*i)->queue_position()) + next_check = i; } - - // lock the session - session_impl::mutex_t::scoped_lock l(m_mutex); - -// INVARIANT_CHECK; - - // is the torrent already active? - if (!find_torrent(info_hash).expired()) - throw duplicate_torrent(); - - // you cannot add new torrents to a session that is closing down - TORRENT_ASSERT(!is_aborted()); - - // create the torrent and the data associated with - // the checker thread and store it before starting - // the thread - boost::shared_ptr torrent_ptr( - new torrent(*this, m_checker_impl, tracker_url, info_hash, name - , save_path, m_listen_interface, storage_mode, 16 * 1024 - , sc, paused)); - torrent_ptr->start(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - boost::shared_ptr tp((*i)(torrent_ptr.get(), userdata)); - if (tp) torrent_ptr->add_extension(tp); - } -#endif - - m_torrents.insert( - std::make_pair(info_hash, torrent_ptr)).first; - - return torrent_handle(this, &m_checker_impl, info_hash); + if (next_check != done) (*next_check)->start_checking(); + m_queued_for_checking.erase(done); } void session_impl::remove_torrent(const torrent_handle& h, int options) { - if (h.m_ses != this) return; - TORRENT_ASSERT(h.m_chk == &m_checker_impl || h.m_chk == 0); - TORRENT_ASSERT(h.m_ses != 0); + boost::shared_ptr tptr = h.m_torrent.lock(); + if (!tptr) +#ifdef BOOST_NO_EXCEPTIONS + return; +#else + throw invalid_handle(); +#endif mutex_t::scoped_lock l(m_mutex); INVARIANT_CHECK; session_impl::torrent_map::iterator i = - m_torrents.find(h.m_info_hash); + m_torrents.find(tptr->torrent_file().info_hash()); + if (i != m_torrents.end()) { torrent& t = *i->second; @@ -1884,40 +1851,27 @@ namespace detail #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) boost::shared_ptr tl(new tracker_logger(*this)); m_tracker_loggers.push_back(tl); - m_tracker_manager.queue_request(m_strand, m_half_open, req + m_tracker_manager.queue_request(m_io_service, m_half_open, req , t.tracker_login(), m_listen_interface.address(), tl); #else - m_tracker_manager.queue_request(m_strand, m_half_open, req + m_tracker_manager.queue_request(m_io_service, m_half_open, req , t.tracker_login(), m_listen_interface.address()); #endif - if (m_alerts.should_post(alert::info)) + if (m_alerts.should_post()) { m_alerts.post_alert( - tracker_announce_alert( - t.get_handle(), "tracker announce, event=stopped")); + tracker_announce_alert(t.get_handle(), req.url)); } } #ifndef NDEBUG sha1_hash i_hash = t.torrent_file().info_hash(); #endif + i->second->set_queue_position(-1); m_torrents.erase(i); TORRENT_ASSERT(m_torrents.find(i_hash) == m_torrents.end()); return; } - - if (h.m_chk) - { - mutex::scoped_lock l(m_checker_impl.m_mutex); - - aux::piece_checker_data* d = m_checker_impl.find_torrent(h.m_info_hash); - if (d != 0) - { - if (d->processing) d->abort = true; - else m_checker_impl.remove_torrent(h.m_info_hash, options); - return; - } - } } bool session_impl::listen_on( @@ -1953,16 +1907,25 @@ namespace detail if (m_dht_same_port) m_dht_settings.service_port = new_interface.port(); // the listen interface changed, rebind the dht listen socket as well - m_dht->rebind(new_interface.address() - , m_dht_settings.service_port); + m_dht_socket.bind(m_dht_settings.service_port); if (m_natpmp.get()) - m_natpmp->set_mappings(0, m_dht_settings.service_port); + { + if (m_udp_mapping[0] != -1) m_natpmp->delete_mapping(m_udp_mapping[0]); + m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp + , m_dht_settings.service_port + , m_dht_settings.service_port); + } if (m_upnp.get()) - m_upnp->set_mappings(0, m_dht_settings.service_port); + { + if (m_udp_mapping[1] != -1) m_upnp->delete_mapping(m_udp_mapping[1]); + m_udp_mapping[1] = m_upnp->add_mapping(upnp::tcp + , m_dht_settings.service_port + , m_dht_settings.service_port); + } } #endif -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING m_logger = create_log("main_session", listen_port(), false); (*m_logger) << time_now_string() << "\n"; #endif @@ -2003,43 +1966,42 @@ namespace detail t->get_policy().peer_from_tracker(peer, peer_id(0), peer_info::lsd, 0); } - void session_impl::on_port_mapping(int tcp_port, int udp_port - , std::string const& errmsg) + void session_impl::on_port_mapping(int mapping, int port + , std::string const& errmsg, int map_transport) { #ifndef TORRENT_DISABLE_DHT - if (udp_port != 0) + if (mapping == m_udp_mapping[map_transport] && port != 0) { - m_external_udp_port = udp_port; - m_dht_settings.service_port = udp_port; - if (m_alerts.should_post(alert::info)) - { - std::stringstream msg; - msg << "successfully mapped UDP port " << udp_port; - m_alerts.post_alert(portmap_alert(msg.str())); - } + m_external_udp_port = port; + m_dht_settings.service_port = port; + if (m_alerts.should_post()) + m_alerts.post_alert(portmap_alert(mapping, port + , map_transport)); + return; } #endif - if (tcp_port != 0) + if (mapping == m_tcp_mapping[map_transport] && port != 0) { if (!m_listen_sockets.empty()) - m_listen_sockets.front().external_port = tcp_port; - if (m_alerts.should_post(alert::info)) - { - std::stringstream msg; - msg << "successfully mapped TCP port " << tcp_port; - m_alerts.post_alert(portmap_alert(msg.str())); - } + m_listen_sockets.front().external_port = port; + if (m_alerts.should_post()) + m_alerts.post_alert(portmap_alert(mapping, port + , map_transport)); + return; } if (!errmsg.empty()) { - if (m_alerts.should_post(alert::warning)) - { - std::stringstream msg; - msg << "Error while mapping ports on NAT router: " << errmsg; - m_alerts.post_alert(portmap_error_alert(msg.str())); - } + if (m_alerts.should_post()) + m_alerts.post_alert(portmap_error_alert(mapping + , map_transport, errmsg)); + } + else + { + if (m_alerts.should_post()) + m_alerts.post_alert(portmap_alert(mapping, port + , map_transport)); } } @@ -2051,11 +2013,14 @@ namespace detail session_status s; + s.num_peers = (int)m_connections.size(); + s.num_unchoked = m_num_unchoked; + s.allowed_upload_slots = m_allowed_upload_slots; + s.up_bandwidth_queue = m_upload_channel.queue_size(); s.down_bandwidth_queue = m_download_channel.queue_size(); s.has_incoming_connections = m_incoming_connection; - s.num_peers = (int)m_connections.size(); s.download_rate = m_stat.download_rate(); s.upload_rate = m_stat.upload_rate(); @@ -2117,13 +2082,23 @@ namespace detail m_dht_settings.service_port = m_listen_interface.port(); } m_external_udp_port = m_dht_settings.service_port; - if (m_natpmp.get()) - m_natpmp->set_mappings(0, m_dht_settings.service_port); - if (m_upnp.get()) - m_upnp->set_mappings(0, m_dht_settings.service_port); - m_dht = new dht::dht_tracker(m_io_service - , m_dht_settings, m_listen_interface.address() - , startup_state); + if (m_natpmp.get() && m_udp_mapping[0] == -1) + { + m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp + , m_dht_settings.service_port + , m_dht_settings.service_port); + } + if (m_upnp.get() && m_udp_mapping[1] == -1) + { + m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp + , m_dht_settings.service_port + , m_dht_settings.service_port); + } + m_dht = new dht::dht_tracker(m_dht_socket, m_dht_settings, startup_state); + if (!m_dht_socket.is_open() || m_dht_socket.local_port() != m_dht_settings.service_port) + { + m_dht_socket.bind(m_dht_settings.service_port); + } } void session_impl::stop_dht() @@ -2148,12 +2123,22 @@ namespace detail && settings.service_port != m_dht_settings.service_port && m_dht) { - m_dht->rebind(m_listen_interface.address() - , settings.service_port); + m_dht_socket.bind(settings.service_port); + if (m_natpmp.get()) - m_natpmp->set_mappings(0, m_dht_settings.service_port); + { + if (m_udp_mapping[0] != -1) m_upnp->delete_mapping(m_udp_mapping[0]); + m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp + , m_dht_settings.service_port + , m_dht_settings.service_port); + } if (m_upnp.get()) - m_upnp->set_mappings(0, m_dht_settings.service_port); + { + if (m_udp_mapping[1] != -1) m_upnp->delete_mapping(m_udp_mapping[1]); + m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp + , m_dht_settings.service_port + , m_dht_settings.service_port); + } m_external_udp_port = settings.service_port; } m_dht_settings = settings; @@ -2205,6 +2190,10 @@ namespace detail #endif abort(); +#ifndef TORRENT_DISABLE_GEO_IP + if (m_asnum_db) GeoIP_delete(m_asnum_db); + if (m_country_db) GeoIP_delete(m_country_db); +#endif #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << time_now_string() << " waiting for main thread\n"; #endif @@ -2212,31 +2201,6 @@ namespace detail TORRENT_ASSERT(m_torrents.empty()); - // it's important that the main thread is closed completely before - // the checker thread is terminated. Because all the connections - // have to be closed and removed from the torrents before they - // can be destructed. (because the weak pointers in the - // peer_connections will be invalidated when the torrents are - // destructed and then the invariant will be broken). - - { - mutex::scoped_lock l(m_checker_impl.m_mutex); - // abort the checker thread - m_checker_impl.m_abort = true; - - // abort the currently checking torrent - if (!m_checker_impl.m_torrents.empty()) - { - m_checker_impl.m_torrents.front()->abort = true; - } - m_checker_impl.m_cond.notify_one(); - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " waiting for checker thread\n"; -#endif - m_checker_thread->join(); - #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << time_now_string() << " waiting for disk io thread\n"; #endif @@ -2257,7 +2221,9 @@ namespace detail INVARIANT_CHECK; if (limit <= 0) limit = (std::numeric_limits::max)(); + if (m_max_uploads == limit) return; m_max_uploads = limit; + m_allowed_upload_slots = limit; } void session_impl::set_max_connections(int limit) @@ -2267,7 +2233,19 @@ namespace detail INVARIANT_CHECK; - if (limit <= 0) limit = (std::numeric_limits::max)(); + if (limit <= 0) + { + limit = (std::numeric_limits::max)(); +#ifndef TORRENT_WINDOWS + rlimit l; + if (getrlimit(RLIMIT_NOFILE, &l) == 0 + && l.rlim_cur != RLIM_INFINITY) + { + limit = l.rlim_cur - m_settings.file_pool_size; + if (limit < 5) limit = 5; + } +#endif + } m_max_connections = limit; } @@ -2321,10 +2299,10 @@ namespace detail return m_alerts.wait_for_alert(max_wait); } - void session_impl::set_severity_level(alert::severity_t s) + void session_impl::set_alert_mask(int m) { mutex_t::scoped_lock l(m_mutex); - m_alerts.set_severity(s); + m_alerts.set_alert_mask(m); } int session_impl::upload_rate_limit() const @@ -2357,47 +2335,61 @@ namespace detail , bind(&session_impl::on_lsd_peer, this, _1, _2)); } - void session_impl::start_natpmp() + natpmp* session_impl::start_natpmp() { mutex_t::scoped_lock l(m_mutex); INVARIANT_CHECK; - if (m_natpmp) return; + if (m_natpmp) return m_natpmp.get(); m_natpmp = new natpmp(m_io_service , m_listen_interface.address() , bind(&session_impl::on_port_mapping - , this, _1, _2, _3)); + , this, _1, _2, _3, 0)); - m_natpmp->set_mappings(m_listen_interface.port(), + if (m_listen_interface.port() > 0) + { + m_tcp_mapping[0] = m_natpmp->add_mapping(natpmp::tcp + , m_listen_interface.port(), m_listen_interface.port()); + } #ifndef TORRENT_DISABLE_DHT - m_dht ? m_dht_settings.service_port : + if (m_dht) + m_udp_mapping[0] = m_natpmp->add_mapping(natpmp::udp + , m_dht_settings.service_port + , m_dht_settings.service_port); #endif - 0); + return m_natpmp.get(); } - void session_impl::start_upnp() + upnp* session_impl::start_upnp() { mutex_t::scoped_lock l(m_mutex); INVARIANT_CHECK; - if (m_upnp) return; + if (m_upnp) return m_upnp.get(); m_upnp = new upnp(m_io_service, m_half_open , m_listen_interface.address() , m_settings.user_agent , bind(&session_impl::on_port_mapping - , this, _1, _2, _3) + , this, _1, _2, _3, 1) , m_settings.upnp_ignore_nonrouters); m_upnp->discover_device(); - m_upnp->set_mappings(m_listen_interface.port(), + if (m_listen_interface.port() > 0) + { + m_tcp_mapping[1] = m_upnp->add_mapping(upnp::tcp + , m_listen_interface.port(), m_listen_interface.port()); + } #ifndef TORRENT_DISABLE_DHT - m_dht ? m_dht_settings.service_port : + if (m_dht) + m_udp_mapping[1] = m_upnp->add_mapping(upnp::udp + , m_dht_settings.service_port + , m_dht_settings.service_port); #endif - 0); + return m_upnp.get(); } void session_impl::stop_lsd() @@ -2420,14 +2412,34 @@ namespace detail { mutex_t::scoped_lock l(m_mutex); if (m_upnp.get()) + { m_upnp->close(); + m_udp_mapping[1] = -1; + m_tcp_mapping[1] = -1; + } m_upnp = 0; } + void session_impl::set_external_address(address const& ip) + { + TORRENT_ASSERT(ip != address()); + + if (m_external_address == ip) return; + + m_external_address = ip; + if (m_alerts.should_post()) + m_alerts.post_alert(external_ip_alert(ip)); + } + void session_impl::free_disk_buffer(char* buf) { m_disk_thread.free_buffer(buf); } + + char* session_impl::allocate_disk_buffer() + { + return m_disk_thread.allocate_buffer(); + } std::pair session_impl::allocate_buffer(int size) { @@ -2437,14 +2449,18 @@ namespace detail boost::mutex::scoped_lock l(m_send_buffer_mutex); #ifdef TORRENT_STATS + TORRENT_ASSERT(m_buffer_allocations >= 0); m_buffer_allocations += num_buffers; m_buffer_usage_logger << log_time() << " protocol_buffer: " << (m_buffer_allocations * send_buffer_size) << std::endl; #endif - std::pair ret((char*)m_send_buffers.ordered_malloc(num_buffers) +#ifdef TORRENT_DISABLE_POOL_ALLOCATOR + int num_bytes = num_buffers * send_buffer_size; + return std::make_pair((char*)malloc(num_bytes), num_bytes); +#else + return std::make_pair((char*)m_send_buffers.ordered_malloc(num_buffers) , num_buffers * send_buffer_size); - if (ret.first == 0) throw std::bad_alloc(); - return ret; +#endif } void session_impl::free_buffer(char* buf, int size) @@ -2461,14 +2477,35 @@ namespace detail m_buffer_usage_logger << log_time() << " protocol_buffer: " << (m_buffer_allocations * send_buffer_size) << std::endl; #endif +#ifdef TORRENT_DISABLE_POOL_ALLOCATOR + free(buf); +#else m_send_buffers.ordered_free(buf, num_buffers); +#endif } #ifndef NDEBUG void session_impl::check_invariant() const { + std::set unique; + int total_downloaders = 0; + for (torrent_map::const_iterator i = m_torrents.begin() + , end(m_torrents.end()); i != end; ++i) + { + int pos = i->second->queue_position(); + if (pos < 0) + { + TORRENT_ASSERT(pos == -1); + continue; + } + ++total_downloaders; + unique.insert(i->second->queue_position()); + } + TORRENT_ASSERT(unique.size() == total_downloaders); + TORRENT_ASSERT(m_max_connections > 0); TORRENT_ASSERT(m_max_uploads > 0); + TORRENT_ASSERT(m_allowed_upload_slots >= m_max_uploads); int unchokes = 0; int num_optimistic = 0; for (connection_map::const_iterator i = m_connections.begin(); @@ -2504,210 +2541,5 @@ namespace detail } #endif - void piece_checker_data::parse_resume_data( - const entry& resume_data - , const torrent_info& info - , std::string& error) - { - // if we don't have any resume data, return - if (resume_data.type() == entry::undefined_t) return; - - entry rd = resume_data; - - try - { - if (rd["file-format"].string() != "libtorrent resume file") - { - error = "missing file format tag"; - return; - } - - if (rd["file-version"].integer() > 1) - { - error = "incompatible file version " - + boost::lexical_cast(rd["file-version"].integer()); - return; - } - - // verify info_hash - sha1_hash hash = rd["info-hash"].string(); - if (hash != info.info_hash()) - { - error = "mismatching info-hash: " + boost::lexical_cast(hash); - return; - } - - // the peers - - if (entry* peers_entry = rd.find_key("peers")) - { - entry::list_type& peer_list = peers_entry->list(); - - std::vector tmp_peers; - tmp_peers.reserve(peer_list.size()); - for (entry::list_type::iterator i = peer_list.begin(); - i != peer_list.end(); ++i) - { - tcp::endpoint a( - address::from_string((*i)["ip"].string()) - , (unsigned short)(*i)["port"].integer()); - tmp_peers.push_back(a); - } - - peers.swap(tmp_peers); - } - - if (entry* banned_peers_entry = rd.find_key("banned_peers")) - { - entry::list_type& peer_list = banned_peers_entry->list(); - - std::vector tmp_peers; - tmp_peers.reserve(peer_list.size()); - for (entry::list_type::iterator i = peer_list.begin(); - i != peer_list.end(); ++i) - { - tcp::endpoint a( - address::from_string((*i)["ip"].string()) - , (unsigned short)(*i)["port"].integer()); - tmp_peers.push_back(a); - } - - banned_peers.swap(tmp_peers); - } - - // read piece map - const entry::list_type& slots = rd["slots"].list(); - if ((int)slots.size() > info.num_pieces()) - { - error = "file has more slots than torrent (slots: " - + boost::lexical_cast(slots.size()) + " size: " - + boost::lexical_cast(info.num_pieces()) + " )"; - return; - } - - std::vector tmp_pieces; - tmp_pieces.reserve(slots.size()); - for (entry::list_type::const_iterator i = slots.begin(); - i != slots.end(); ++i) - { - int index = (int)i->integer(); - if (index >= info.num_pieces() || index < -2) - { - error = "too high index number in slot map (index: " - + boost::lexical_cast(index) + " size: " - + boost::lexical_cast(info.num_pieces()) + ")"; - return; - } - tmp_pieces.push_back(index); - } - - // only bother to check the partial pieces if we have the same block size - // as in the fast resume data. If the blocksize has changed, then throw - // away all partial pieces. - std::vector tmp_unfinished; - int num_blocks_per_piece = (int)rd["blocks per piece"].integer(); - if (num_blocks_per_piece == info.piece_length() / torrent_ptr->block_size()) - { - // the unfinished pieces - - entry::list_type& unfinished = rd["unfinished"].list(); - int unfinished_size = int(unfinished.size()); - block_info.resize(num_blocks_per_piece * unfinished_size); - tmp_unfinished.reserve(unfinished_size); - int index = 0; - for (entry::list_type::iterator i = unfinished.begin(); - i != unfinished.end(); ++i, ++index) - { - piece_picker::downloading_piece p; - p.info = &block_info[index * num_blocks_per_piece]; - p.index = (int)(*i)["piece"].integer(); - if (p.index < 0 || p.index >= info.num_pieces()) - { - error = "invalid piece index in unfinished piece list (index: " - + boost::lexical_cast(p.index) + " size: " - + boost::lexical_cast(info.num_pieces()) + ")"; - return; - } - - const std::string& bitmask = (*i)["bitmask"].string(); - - const int num_bitmask_bytes = (std::max)(num_blocks_per_piece / 8, 1); - if ((int)bitmask.size() != num_bitmask_bytes) - { - error = "invalid size of bitmask (" + boost::lexical_cast(bitmask.size()) + ")"; - return; - } - for (int j = 0; j < num_bitmask_bytes; ++j) - { - unsigned char bits = bitmask[j]; - int num_bits = (std::min)(num_blocks_per_piece - j*8, 8); - for (int k = 0; k < num_bits; ++k) - { - const int bit = j * 8 + k; - if (bits & (1 << k)) - { - p.info[bit].state = piece_picker::block_info::state_finished; - ++p.finished; - } - } - } - - if (p.finished == 0) continue; - - std::vector::iterator slot_iter - = std::find(tmp_pieces.begin(), tmp_pieces.end(), p.index); - if (slot_iter == tmp_pieces.end()) - { - // this piece is marked as unfinished - // but doesn't have any storage - error = "piece " + boost::lexical_cast(p.index) + " is " - "marked as unfinished, but doesn't have any storage"; - return; - } - - TORRENT_ASSERT(*slot_iter == p.index); - int slot_index = static_cast(slot_iter - tmp_pieces.begin()); - const entry* ad = i->find_key("adler32"); - - if (ad && ad->type() == entry::int_t) - { - unsigned long adler - = torrent_ptr->filesystem().piece_crc( - slot_index - , torrent_ptr->block_size() - , p.info); - - // crc's didn't match, don't use the resume data - if (ad->integer() != entry::integer_type(adler)) - { - error = "checksum mismatch on piece " - + boost::lexical_cast(p.index); - return; - } - } - - tmp_unfinished.push_back(p); - } - } - - if (!torrent_ptr->verify_resume_data(rd, error)) - return; - - piece_map.swap(tmp_pieces); - unfinished_pieces.swap(tmp_unfinished); - } - catch (invalid_encoding&) - { - return; - } - catch (type_error&) - { - return; - } - catch (file_error&) - { - return; - } - } }} diff --git a/libtorrent/src/smart_ban.cpp b/libtorrent/src/smart_ban.cpp new file mode 100644 index 000000000..a3db95e2b --- /dev/null +++ b/libtorrent/src/smart_ban.cpp @@ -0,0 +1,303 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +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. + +*/ + +#include "libtorrent/pch.hpp" + +#ifdef _MSC_VER +#pragma warning(push, 1) +#endif + +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include +#include +#include +#include +#include + +#include "libtorrent/peer_connection.hpp" +#include "libtorrent/bt_peer_connection.hpp" +#include "libtorrent/hasher.hpp" +#include "libtorrent/bencode.hpp" +#include "libtorrent/torrent.hpp" +#include "libtorrent/extensions.hpp" +#include "libtorrent/extensions/smart_ban.hpp" +#include "libtorrent/alert_types.hpp" +#include "libtorrent/disk_io_thread.hpp" +#include "libtorrent/aux_/session_impl.hpp" + +namespace libtorrent { namespace +{ + + struct smart_ban_plugin : torrent_plugin, boost::enable_shared_from_this + { + smart_ban_plugin(torrent& t) + : m_torrent(t) + , m_salt(rand()) + { + } + + void on_piece_pass(int p) + { +#ifdef TORRENT_LOGGING + (*m_torrent.session().m_logger) << time_now_string() << " PIECE PASS [ p: " << p + << " | block_crc_size: " << m_block_crc.size() << " ]\n"; +#endif + // has this piece failed earlier? If it has, go through the + // CRCs from the time it failed and ban the peers that + // sent bad blocks + std::map::iterator i = m_block_crc.lower_bound(piece_block(p, 0)); + if (i == m_block_crc.end() || i->first.piece_index != p) return; + + int size = m_torrent.torrent_file().piece_size(p); + peer_request r = {p, 0, (std::min)(16*1024, size)}; + piece_block pb(p, 0); + while (size > 0) + { + if (i->first.block_index == pb.block_index) + { + m_torrent.filesystem().async_read(r, bind(&smart_ban_plugin::on_read_ok_block + , shared_from_this(), *i, _1, _2)); + m_block_crc.erase(i++); + } + else + { + TORRENT_ASSERT(i->first.block_index > pb.block_index); + } + + if (i == m_block_crc.end() || i->first.piece_index != p) + break; + + r.start += 16*1024; + size -= 16*1024; + r.length = (std::min)(16*1024, size); + ++pb.block_index; + } + +#ifndef NDEBUG + // make sure we actually removed all the entries for piece 'p' + i = m_block_crc.lower_bound(piece_block(p, 0)); + TORRENT_ASSERT(i == m_block_crc.end() || i->first.piece_index != p); +#endif + + if (m_torrent.is_seed()) + { + std::map().swap(m_block_crc); + return; + } + } + + void on_piece_failed(int p) + { + // The piece failed the hash check. Record + // the CRC and origin peer of every block + + // if the torrent is aborted, no point in starting + // a bunch of read operations on it + if (m_torrent.is_aborted()) return; + + std::vector downloaders; + m_torrent.picker().get_downloaders(downloaders, p); + + int size = m_torrent.torrent_file().piece_size(p); + peer_request r = {p, 0, (std::min)(16*1024, size)}; + piece_block pb(p, 0); + for (std::vector::iterator i = downloaders.begin() + , end(downloaders.end()); i != end; ++i) + { + if (*i != 0) + { + m_torrent.filesystem().async_read(r, bind(&smart_ban_plugin::on_read_failed_block + , shared_from_this(), pb, (policy::peer*)*i, _1, _2)); + } + + r.start += 16*1024; + size -= 16*1024; + r.length = (std::min)(16*1024, size); + ++pb.block_index; + } + TORRENT_ASSERT(size <= 0); + } + + private: + + // this entry ties a specific block CRC to + // a peer. + struct block_entry + { + policy::peer* peer; + unsigned long crc; + }; + + void on_read_failed_block(piece_block b, policy::peer* p, int ret, disk_io_job const& j) + { + TORRENT_ASSERT(p); + // ignore read errors + if (ret != j.buffer_size) return; + + adler32_crc crc; + crc.update(j.buffer, j.buffer_size); + crc.update((char const*)&m_salt, sizeof(m_salt)); + + block_entry e = {p, crc.final()}; + + // since this callback is called directory from the disk io + // thread, the session mutex is not locked when we get here + aux::session_impl::mutex_t::scoped_lock l(m_torrent.session().m_mutex); + + std::map::iterator i = m_block_crc.lower_bound(b); + if (i != m_block_crc.end() && i->first == b && i->second.peer == p) + { + // this peer has sent us this block before + if (i->second.crc != e.crc) + { + // this time the crc of the block is different + // from the first time it sent it + // at least one of them must be bad + + if (p == 0) return; + if (!m_torrent.get_policy().has_peer(p)) return; + +#ifdef TORRENT_LOGGING + char const* client = "-"; + peer_info info; + if (p->connection) + { + p->connection->get_peer_info(info); + client = info.client.c_str(); + } + (*m_torrent.session().m_logger) << time_now_string() << " BANNING PEER [ p: " << b.piece_index + << " | b: " << b.block_index + << " | c: " << client + << " | crc1: " << i->second.crc + << " | crc2: " << e.crc + << " | ip: " << p->ip << " ]\n"; +#endif + p->banned = true; + if (p->connection) p->connection->disconnect("banning peer for sending bad data"); + } + // we already have this exact entry in the map + // we don't have to insert it + return; + } + + m_block_crc.insert(i, std::make_pair(b, e)); + +#ifdef TORRENT_LOGGING + char const* client = "-"; + peer_info info; + if (p->connection) + { + p->connection->get_peer_info(info); + client = info.client.c_str(); + } + (*m_torrent.session().m_logger) << time_now_string() << " STORE BLOCK CRC [ p: " << b.piece_index + << " | b: " << b.block_index + << " | c: " << client + << " | crc: " << e.crc + << " | ip: " << p->ip << " ]\n"; +#endif + } + + void on_read_ok_block(std::pair b, int ret, disk_io_job const& j) + { + // since this callback is called directory from the disk io + // thread, the session mutex is not locked when we get here + aux::session_impl::mutex_t::scoped_lock l(m_torrent.session().m_mutex); + + // ignore read errors + if (ret != j.buffer_size) return; + + adler32_crc crc; + crc.update(j.buffer, j.buffer_size); + crc.update((char const*)&m_salt, sizeof(m_salt)); + unsigned long ok_crc = crc.final(); + + if (b.second.crc == ok_crc) return; + + policy::peer* p = b.second.peer; + + if (p == 0) return; + if (!m_torrent.get_policy().has_peer(p)) return; + +#ifdef TORRENT_LOGGING + char const* client = "-"; + peer_info info; + if (p->connection) + { + p->connection->get_peer_info(info); + client = info.client.c_str(); + } + (*m_torrent.session().m_logger) << time_now_string() << " BANNING PEER [ p: " << b.first.piece_index + << " | b: " << b.first.block_index + << " | c: " << client + << " | ok_crc: " << ok_crc + << " | bad_crc: " << b.second.crc + << " | ip: " << p->ip << " ]\n"; +#endif + p->banned = true; + if (p->connection) p->connection->disconnect("banning peer for sending bad data"); + } + + torrent& m_torrent; + + // This table maps a piece_block (piece and block index + // pair) to a peer and the block CRC. The CRC is calculated + // from the data in the block + the salt + std::map m_block_crc; + + // This salt is a random value used to calculate the block CRCs + // Since the CRC function that is used is not a one way function + // the salt is required to avoid attacks where bad data is sent + // that is forged to match the CRC of the good data. + int m_salt; + }; + +} } + +namespace libtorrent +{ + + boost::shared_ptr create_smart_ban_plugin(torrent* t, void*) + { + return boost::shared_ptr(new smart_ban_plugin(*t)); + } + +} + + diff --git a/libtorrent/src/socks4_stream.cpp b/libtorrent/src/socks4_stream.cpp index c96dde85b..e4add5d4f 100644 --- a/libtorrent/src/socks4_stream.cpp +++ b/libtorrent/src/socks4_stream.cpp @@ -37,13 +37,13 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { - void socks4_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i + void socks4_stream::name_lookup(error_code const& e, tcp::resolver::iterator i , boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -54,7 +54,7 @@ namespace libtorrent if (i == tcp::resolver::iterator()) { - asio::error_code ec = asio::error::operation_not_supported; + error_code ec = asio::error::operation_not_supported; (*h)(ec); close(ec); return; @@ -64,12 +64,12 @@ namespace libtorrent &socks4_stream::connected, this, _1, h)); } - void socks4_stream::connected(asio::error_code const& e, boost::shared_ptr h) + void socks4_stream::connected(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -86,31 +86,31 @@ namespace libtorrent p += m_user.size(); write_uint8(0, p); // NULL terminator - asio::async_write(m_sock, asio::buffer(m_buffer) + async_write(m_sock, asio::buffer(m_buffer) , boost::bind(&socks4_stream::handshake1, this, _1, h)); } - void socks4_stream::handshake1(asio::error_code const& e, boost::shared_ptr h) + void socks4_stream::handshake1(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } m_buffer.resize(8); - asio::async_read(m_sock, asio::buffer(m_buffer) + async_read(m_sock, asio::buffer(m_buffer) , boost::bind(&socks4_stream::handshake2, this, _1, h)); } - void socks4_stream::handshake2(asio::error_code const& e, boost::shared_ptr h) + void socks4_stream::handshake2(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -123,7 +123,7 @@ namespace libtorrent if (reply_version != 0) { - asio::error_code ec = asio::error::operation_not_supported; + error_code ec = asio::error::operation_not_supported; (*h)(ec); close(ec); return; @@ -137,7 +137,7 @@ namespace libtorrent return; } - asio::error_code ec = asio::error::fault; + error_code ec = asio::error::fault; switch (status_code) { case 91: ec = asio::error::connection_refused; break; diff --git a/libtorrent/src/socks5_stream.cpp b/libtorrent/src/socks5_stream.cpp index f0c41c02b..3fb9ec666 100644 --- a/libtorrent/src/socks5_stream.cpp +++ b/libtorrent/src/socks5_stream.cpp @@ -38,13 +38,13 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { - void socks5_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i + void socks5_stream::name_lookup(error_code const& e, tcp::resolver::iterator i , boost::shared_ptr h) { if (e || i == tcp::resolver::iterator()) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -53,12 +53,12 @@ namespace libtorrent &socks5_stream::connected, this, _1, h)); } - void socks5_stream::connected(asio::error_code const& e, boost::shared_ptr h) + void socks5_stream::connected(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -79,31 +79,31 @@ namespace libtorrent write_uint8(0, p); // no authentication write_uint8(2, p); // username/password } - asio::async_write(m_sock, asio::buffer(m_buffer) + async_write(m_sock, asio::buffer(m_buffer) , boost::bind(&socks5_stream::handshake1, this, _1, h)); } - void socks5_stream::handshake1(asio::error_code const& e, boost::shared_ptr h) + void socks5_stream::handshake1(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } m_buffer.resize(2); - asio::async_read(m_sock, asio::buffer(m_buffer) + async_read(m_sock, asio::buffer(m_buffer) , boost::bind(&socks5_stream::handshake2, this, _1, h)); } - void socks5_stream::handshake2(asio::error_code const& e, boost::shared_ptr h) + void socks5_stream::handshake2(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -117,7 +117,7 @@ namespace libtorrent if (version < 5) { (*h)(asio::error::operation_not_supported); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -131,7 +131,7 @@ namespace libtorrent if (m_user.empty()) { (*h)(asio::error::operation_not_supported); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -144,41 +144,41 @@ namespace libtorrent write_string(m_user, p); write_uint8(m_password.size(), p); write_string(m_password, p); - asio::async_write(m_sock, asio::buffer(m_buffer) + async_write(m_sock, asio::buffer(m_buffer) , boost::bind(&socks5_stream::handshake3, this, _1, h)); } else { (*h)(asio::error::operation_not_supported); - asio::error_code ec; + error_code ec; close(ec); return; } } - void socks5_stream::handshake3(asio::error_code const& e + void socks5_stream::handshake3(error_code const& e , boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } m_buffer.resize(2); - asio::async_read(m_sock, asio::buffer(m_buffer) + async_read(m_sock, asio::buffer(m_buffer) , boost::bind(&socks5_stream::handshake4, this, _1, h)); } - void socks5_stream::handshake4(asio::error_code const& e + void socks5_stream::handshake4(error_code const& e , boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -192,7 +192,7 @@ namespace libtorrent if (version != 1) { (*h)(asio::error::operation_not_supported); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -200,7 +200,7 @@ namespace libtorrent if (status != 0) { (*h)(asio::error::operation_not_supported); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -220,35 +220,34 @@ namespace libtorrent write_uint8(1, p); // CONNECT command write_uint8(0, p); // reserved write_uint8(m_remote_endpoint.address().is_v4()?1:4, p); // address type - write_address(m_remote_endpoint.address(), p); - write_uint16(m_remote_endpoint.port(), p); + write_endpoint(m_remote_endpoint, p); TORRENT_ASSERT(p - &m_buffer[0] == int(m_buffer.size())); - asio::async_write(m_sock, asio::buffer(m_buffer) + async_write(m_sock, asio::buffer(m_buffer) , boost::bind(&socks5_stream::connect1, this, _1, h)); } - void socks5_stream::connect1(asio::error_code const& e, boost::shared_ptr h) + void socks5_stream::connect1(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } m_buffer.resize(6 + 4); // assume an IPv4 address - asio::async_read(m_sock, asio::buffer(m_buffer) + async_read(m_sock, asio::buffer(m_buffer) , boost::bind(&socks5_stream::connect2, this, _1, h)); } - void socks5_stream::connect2(asio::error_code const& e, boost::shared_ptr h) + void socks5_stream::connect2(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -261,14 +260,14 @@ namespace libtorrent if (version < 5) { (*h)(asio::error::operation_not_supported); - asio::error_code ec; + error_code ec; close(ec); return; } int response = read_uint8(p); if (response != 0) { - asio::error_code e = asio::error::fault; + error_code e = asio::error::fault; switch (response) { case 1: e = asio::error::fault; break; @@ -281,7 +280,7 @@ namespace libtorrent case 8: e = asio::error::address_family_not_supported; break; } (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } @@ -306,22 +305,22 @@ namespace libtorrent else { (*h)(asio::error::operation_not_supported); - asio::error_code ec; + error_code ec; close(ec); return; } m_buffer.resize(skip_bytes); - asio::async_read(m_sock, asio::buffer(m_buffer) + async_read(m_sock, asio::buffer(m_buffer) , boost::bind(&socks5_stream::connect3, this, _1, h)); } - void socks5_stream::connect3(asio::error_code const& e, boost::shared_ptr h) + void socks5_stream::connect3(error_code const& e, boost::shared_ptr h) { if (e) { (*h)(e); - asio::error_code ec; + error_code ec; close(ec); return; } diff --git a/libtorrent/src/stat.cpp b/libtorrent/src/stat.cpp index d695edc42..18a3285f8 100755 --- a/libtorrent/src/stat.cpp +++ b/libtorrent/src/stat.cpp @@ -47,47 +47,23 @@ POSSIBILITY OF SUCH DAMAGE. #define for if (false) {} else for #endif -using namespace libtorrent; +namespace libtorrent +{ -void libtorrent::stat::second_tick(float tick_interval) +void stat_channel::second_tick(float tick_interval) { INVARIANT_CHECK; + m_rate_sum -= m_rate_history[history-1]; + for (int i = history - 2; i >= 0; --i) - { - m_download_rate_history[i + 1] = m_download_rate_history[i]; - m_upload_rate_history[i + 1] = m_upload_rate_history[i]; - m_download_payload_rate_history[i + 1] = m_download_payload_rate_history[i]; - m_upload_payload_rate_history[i + 1] = m_upload_payload_rate_history[i]; - } + m_rate_history[i + 1] = m_rate_history[i]; - m_download_rate_history[0] = (m_downloaded_payload + m_downloaded_protocol) - / tick_interval; - m_upload_rate_history[0] = (m_uploaded_payload + m_uploaded_protocol) - / tick_interval; - m_download_payload_rate_history[0] = m_downloaded_payload / tick_interval; - m_upload_payload_rate_history[0] = m_uploaded_payload / tick_interval; - - m_downloaded_payload = 0; - m_uploaded_payload = 0; - m_downloaded_protocol = 0; - m_uploaded_protocol = 0; - - m_mean_download_rate = 0; - m_mean_upload_rate = 0; - m_mean_download_payload_rate = 0; - m_mean_upload_payload_rate = 0; - - for (int i = 0; i < history; ++i) - { - m_mean_download_rate += m_download_rate_history[i]; - m_mean_upload_rate += m_upload_rate_history[i]; - m_mean_download_payload_rate += m_download_payload_rate_history[i]; - m_mean_upload_payload_rate += m_upload_payload_rate_history[i]; - } - - m_mean_download_rate /= history; - m_mean_upload_rate /= history; - m_mean_download_payload_rate /= history; - m_mean_upload_payload_rate /= history; + m_rate_history[0] = m_counter / tick_interval; + m_rate_sum += m_rate_history[0]; + m_counter = 0; } + + +} + diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index 7e94a175e..d6ecd4e71 100755 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -67,6 +67,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/invariant_check.hpp" #include "libtorrent/file_pool.hpp" #include "libtorrent/aux_/session_impl.hpp" +#include "libtorrent/disk_buffer_holder.hpp" #ifndef NDEBUG #include @@ -251,7 +252,6 @@ namespace namespace libtorrent { - template void recursive_copy(Path const& old_path, Path const& new_path, std::string& error) { @@ -300,32 +300,32 @@ namespace libtorrent #endif } std::vector > get_filesizes( - torrent_info const& t, fs::path p) + file_storage const& s, fs::path p) { p = complete(p); std::vector > sizes; - for (torrent_info::file_iterator i = t.begin_files(true); - i != t.end_files(true); ++i) + for (file_storage::iterator i = s.begin() + , end(s.end());i != end; ++i) { size_type size = 0; std::time_t time = 0; - try - { -#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 - fs::path f = p / i->path; - size = file_size_win(f); - time = last_write_time_win(f); -#elif TORRENT_USE_WPATH - fs::wpath f = safe_convert((p / i->path).string()); - size = file_size(f); - time = last_write_time(f); +#if TORRENT_USE_WPATH + fs::wpath f = safe_convert((p / i->path).string()); #else - fs::path f = p / i->path; + fs::path f = p / i->path; +#endif +#ifndef BOOST_NO_EXCEPTIONS + try +#else + if (exists(f)) +#endif + { size = file_size(f); time = last_write_time(f); -#endif } +#ifndef BOOST_NO_EXCEPTIONS catch (std::exception&) {} +#endif sizes.push_back(std::make_pair(size, time)); } return sizes; @@ -338,13 +338,13 @@ namespace libtorrent // pieces, so any older version of the resume data will // still be a correct subset of the actual data on disk. bool match_filesizes( - torrent_info const& t + file_storage const& fs , fs::path p , std::vector > const& sizes , bool compact_mode , std::string* error) { - if ((int)sizes.size() != t.num_files(true)) + if ((int)sizes.size() != fs.num_files()) { if (error) *error = "mismatching number of files"; return false; @@ -353,28 +353,29 @@ namespace libtorrent std::vector >::const_iterator s = sizes.begin(); - for (torrent_info::file_iterator i = t.begin_files(true); - i != t.end_files(true); ++i, ++s) + for (file_storage::iterator i = fs.begin() + , end(fs.end());i != end; ++i, ++s) { size_type size = 0; std::time_t time = 0; - try - { -#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 - fs::path f = p / i->path; - size = file_size_win(f); - time = last_write_time_win(f); -#elif TORRENT_USE_WPATH - fs::wpath f = safe_convert((p / i->path).string()); - size = file_size(f); - time = last_write_time(f); + +#if TORRENT_USE_WPATH + fs::wpath f = safe_convert((p / i->path).string()); #else - fs::path f = p / i->path; + fs::path f = p / i->path; +#endif +#ifndef BOOST_NO_EXCEPTIONS + try +#else + if (exists(f)) +#endif + { size = file_size(f); time = last_write_time(f); -#endif } +#ifndef BOOST_NO_EXCEPTIONS catch (std::exception&) {} +#endif if ((compact_mode && size != s->first) || (!compact_mode && size < s->first)) { @@ -402,39 +403,44 @@ namespace libtorrent class storage : public storage_interface, boost::noncopyable { public: - storage(boost::intrusive_ptr info, fs::path const& path, file_pool& fp) - : m_info(info) - , m_files(fp) + storage(file_storage const& fs, fs::path const& path, file_pool& fp) + : m_files(fs) + , m_pool(fp) { - TORRENT_ASSERT(info->begin_files(true) != info->end_files(true)); + TORRENT_ASSERT(m_files.begin() != m_files.end()); m_save_path = fs::complete(path); TORRENT_ASSERT(m_save_path.is_complete()); } - void release_files(); - void delete_files(); - void initialize(bool allocate_files); + bool rename_file(int index, std::string const& new_filename); + bool release_files(); + bool delete_files(); + bool initialize(bool allocate_files); bool move_storage(fs::path save_path); - size_type read(char* buf, int slot, int offset, int size); - void write(const char* buf, int slot, int offset, int size); - void move_slot(int src_slot, int dst_slot); - void swap_slots(int slot1, int slot2); - void swap_slots3(int slot1, int slot2, int slot3); - bool verify_resume_data(entry& rd, std::string& error); - void write_resume_data(entry& rd) const; + int read(char* buf, int slot, int offset, int size); + int write(const char* buf, int slot, int offset, int size); + bool move_slot(int src_slot, int dst_slot); + bool swap_slots(int slot1, int slot2); + bool swap_slots3(int slot1, int slot2, int slot3); + bool verify_resume_data(lazy_entry const& rd, std::string& error); + bool write_resume_data(entry& rd) const; sha1_hash hash_for_slot(int slot, partial_hash& ph, int piece_size); - size_type read_impl(char* buf, int slot, int offset, int size, bool fill_zero); + int read_impl(char* buf, int slot, int offset, int size, bool fill_zero); ~storage() - { m_files.release(this); } + { m_pool.release(this); } + + file_storage const& files() const { return m_mapped_files?*m_mapped_files:m_files; } + + boost::scoped_ptr m_mapped_files; + file_storage const& m_files; - boost::intrusive_ptr m_info; fs::path m_save_path; // the file pool is typically stored in // the session, to make all storage // instances use the same pool - file_pool& m_files; + file_pool& m_pool; // temporary storage for moving pieces buffer m_scratch_buffer; @@ -470,12 +476,12 @@ namespace libtorrent #endif } - void storage::initialize(bool allocate_files) + bool storage::initialize(bool allocate_files) { // first, create all missing directories fs::path last_path; - for (torrent_info::file_iterator file_iter = m_info->begin_files(true), - end_iter = m_info->end_files(true); file_iter != end_iter; ++file_iter) + for (file_storage::iterator file_iter = files().begin(), + end_iter = files().end(); file_iter != end_iter; ++file_iter) { fs::path dir = (m_save_path / file_iter->path).branch_path(); @@ -502,43 +508,102 @@ namespace libtorrent // the directory exists. if (file_iter->size == 0) { +#ifndef BOOST_NO_EXCEPTIONS try { - file(m_save_path / file_iter->path, file::out); - } catch (std::exception&) {} +#endif + file(m_save_path / file_iter->path, file::out); +#ifndef BOOST_NO_EXCEPTIONS + } + catch (std::exception& e) + { + set_error((m_save_path / file_iter->path).string(), e.what()); + return true; + } +#endif continue; } +#ifndef BOOST_NO_EXCEPTIONS try { - if (allocate_files) - { - m_files.open_file(this, m_save_path / file_iter->path, file::in | file::out) - ->set_size(file_iter->size); - } - } catch (std::exception&) {} +#endif + if (allocate_files) + { + std::string error; + boost::shared_ptr f = m_pool.open_file(this + , m_save_path / file_iter->path, file::in | file::out + , error); + if (f && f->error().empty()) + f->set_size(file_iter->size); + } +#ifndef BOOST_NO_EXCEPTIONS + } + catch (std::exception& e) + { + set_error((m_save_path / file_iter->path).string(), e.what()); + return true; + } +#endif } // close files that were opened in write mode - m_files.release(this); + m_pool.release(this); + return false; } - void storage::release_files() + bool storage::rename_file(int index, std::string const& new_filename) { - m_files.release(this); - buffer().swap(m_scratch_buffer); + if (index < 0 || index >= m_files.num_files()) return true; + fs::path old_name = m_save_path / files().at(index).path; + m_pool.release(old_name); + +#if TORRENT_USE_WPATH + fs::wpath old_path = safe_convert(old_name.string()); + fs::wpath new_path = safe_convert((m_save_path / new_filename).string()); +#else + fs::path const& old_path = old_name; + fs::path new_path = m_save_path / new_filename; +#endif + +#ifndef BOOST_NO_EXCEPTIONS + try + { +#endif + rename(old_path, new_path); + if (!m_mapped_files) + { m_mapped_files.reset(new file_storage(m_files)); } + m_mapped_files->rename_file(index, new_filename); +#ifndef BOOST_NO_EXCEPTIONS + } + catch (std::exception& e) + { + set_error(old_name.string(), e.what()); + return true; + } +#endif + return false; } - void storage::delete_files() + bool storage::release_files() + { + m_pool.release(this); + buffer().swap(m_scratch_buffer); + return false; + } + + bool storage::delete_files() { // make sure we don't have the files open - m_files.release(this); + m_pool.release(this); buffer().swap(m_scratch_buffer); + int result = 0; std::string error; + std::string error_file; // delete the files from disk std::set directories; typedef std::set::iterator iter_t; - for (torrent_info::file_iterator i = m_info->begin_files(true) - , end(m_info->end_files(true)); i != end; ++i) + for (file_storage::iterator i = files().begin() + , end(files().end()); i != end; ++i) { std::string p = (m_save_path / i->path).string(); fs::path bp = i->path.branch_path(); @@ -553,10 +618,18 @@ namespace libtorrent try { fs::remove(safe_convert(p)); } catch (std::exception& e) - { error = e.what(); } + { + error = e.what(); + error_file = p; + result = 1; + } #else if (std::remove(p.c_str()) != 0 && errno != ENOENT) + { error = std::strerror(errno); + error_file = p; + result = errno; + } #endif } @@ -570,22 +643,36 @@ namespace libtorrent try { fs::remove(safe_convert(*i)); } catch (std::exception& e) - { error = e.what(); } + { + error = e.what(); + error_file = *i; + result = 1; + } #else if (std::remove(i->c_str()) != 0 && errno != ENOENT) + { error = std::strerror(errno); + error_file = *i; + result = errno; + } #endif } - if (!error.empty()) throw std::runtime_error(error); + if (!error.empty()) + { + m_error.swap(error); + m_error_file.swap(error_file); + } + return result != 0; } - void storage::write_resume_data(entry& rd) const + bool storage::write_resume_data(entry& rd) const { - std::vector > file_sizes - = get_filesizes(*m_info, m_save_path); + TORRENT_ASSERT(rd.type() == entry::dictionary_t); + + std::vector > file_sizes + = get_filesizes(files(), m_save_path); - rd["file sizes"] = entry::list_type(); entry::list_type& fl = rd["file sizes"].list(); for (std::vector >::iterator i = file_sizes.begin(), end(file_sizes.end()); i != end; ++i) @@ -595,19 +682,35 @@ namespace libtorrent p.push_back(entry(i->second)); fl.push_back(entry(p)); } + return false; } - bool storage::verify_resume_data(entry& rd, std::string& error) + bool storage::verify_resume_data(lazy_entry const& rd, std::string& error) { - std::vector > file_sizes; - entry::list_type& l = rd["file sizes"].list(); - - for (entry::list_type::iterator i = l.begin(); - i != l.end(); ++i) + if (rd.type() != lazy_entry::dict_t) { - file_sizes.push_back(std::make_pair( - i->list().front().integer() - , std::time_t(i->list().back().integer()))); + error = "invalid fastresume file (not a dictionary)"; + return true; + } + + std::vector > file_sizes; + lazy_entry const* file_sizes_ent = rd.dict_find_list("file sizes"); + if (file_sizes_ent == 0) + { + error = "missing or invalid 'file sizes' entry in resume data"; + return false; + } + + for (int i = 0; i < file_sizes_ent->list_size(); ++i) + { + lazy_entry const* e = file_sizes_ent->list_at(i); + if (e->type() != lazy_entry::list_t + || e->list_size() != 2 + || e->list_at(0)->type() != lazy_entry::int_t + || e->list_at(1)->type() != lazy_entry::int_t) + continue; + file_sizes.push_back(std::pair( + e->list_int_value_at(0), std::time_t(e->list_int_value_at(1)))); } if (file_sizes.empty()) @@ -616,27 +719,38 @@ namespace libtorrent return false; } - entry::list_type& slots = rd["slots"].list(); - bool seed = int(slots.size()) == m_info->num_pieces() - && std::find_if(slots.begin(), slots.end() - , boost::bind(std::less() - , boost::bind((size_type const& (entry::*)() const) - &entry::integer, _1), 0)) == slots.end(); + lazy_entry const* slots = rd.dict_find_list("slots"); + if (slots == 0) + { + error = "missing or invalid 'slots' entry in resume data"; + return false; + } + + bool seed = false; + + if (int(slots->list_size()) == m_files.num_pieces()) + { + bool seed = true; + for (int i = 0; i < slots->list_size(); ++i) + { + lazy_entry const* e = slots->list_at(i); + if (e->list_int_value_at(i, -1) >= 0) continue; + seed = false; + break; + } + } bool full_allocation_mode = false; - try - { - full_allocation_mode = rd["allocation"].string() == "full"; - } - catch (std::exception&) {} + if (rd.dict_find_string_value("allocation") == "full") + full_allocation_mode = true; if (seed) { - if (m_info->num_files(true) != (int)file_sizes.size()) + if (files().num_files() != (int)file_sizes.size()) { error = "the number of files does not match the torrent (num: " + boost::lexical_cast(file_sizes.size()) + " actual: " - + boost::lexical_cast(m_info->num_files(true)) + ")"; + + boost::lexical_cast(files().num_files()) + ")"; return false; } @@ -644,8 +758,8 @@ namespace libtorrent fs = file_sizes.begin(); // the resume data says we have the entire torrent // make sure the file sizes are the right ones - for (torrent_info::file_iterator i = m_info->begin_files(true) - , end(m_info->end_files(true)); i != end; ++i, ++fs) + for (file_storage::iterator i = files().begin() + , end(files().end()); i != end; ++i, ++fs) { if (i->size != fs->first) { @@ -657,7 +771,7 @@ namespace libtorrent } } - return match_filesizes(*m_info, m_save_path, file_sizes + return match_filesizes(files(), m_save_path, file_sizes , !full_allocation_mode, &error); } @@ -693,45 +807,50 @@ namespace libtorrent return false; #endif - m_files.release(this); + m_pool.release(this); #if TORRENT_USE_WPATH - old_path = safe_convert((m_save_path / m_info->name()).string()); - new_path = safe_convert((save_path / m_info->name()).string()); + old_path = safe_convert((m_save_path / files().name()).string()); + new_path = safe_convert((save_path / files().name()).string()); #else - old_path = m_save_path / m_info->name(); - new_path = save_path / m_info->name(); + old_path = m_save_path / files().name(); + new_path = save_path / files().name(); #endif +#ifndef BOOST_NO_EXCEPTIONS try { +#endif #if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 rename_win(old_path, new_path); - rename(old_path, new_path); #else rename(old_path, new_path); #endif m_save_path = save_path; return true; +#ifndef BOOST_NO_EXCEPTIONS } catch (std::exception& e) - { + { std::string err; recursive_copy(old_path, new_path, err); if (!err.empty()) { + set_error((m_save_path / files().name()).string(), e.what()); return true; } m_save_path = save_path; recursive_remove(old_path); - } + } +#endif + return false; } #ifndef NDEBUG /* void storage::shuffle() { - int num_pieces = m_info->num_pieces(); + int num_pieces = files().num_pieces(); std::vector pieces(num_pieces); for (std::vector::iterator i = pieces.begin(); @@ -748,7 +867,7 @@ namespace libtorrent { const int slot_index = targets[i]; const int piece_index = pieces[i]; - const int slot_size =static_cast(m_info->piece_size(slot_index)); + const int slot_size =static_cast(m_files.piece_size(slot_index)); std::vector buf(slot_size); read(&buf[0], piece_index, 0, slot_size); write(&buf[0], slot_index, 0, slot_size); @@ -757,44 +876,50 @@ namespace libtorrent */ #endif - void storage::move_slot(int src_slot, int dst_slot) + bool storage::move_slot(int src_slot, int dst_slot) { - int piece_size = m_info->piece_size(dst_slot); + int piece_size = m_files.piece_size(dst_slot); m_scratch_buffer.resize(piece_size); - read_impl(&m_scratch_buffer[0], src_slot, 0, piece_size, true); - write(&m_scratch_buffer[0], dst_slot, 0, piece_size); + int ret1 = read_impl(&m_scratch_buffer[0], src_slot, 0, piece_size, true); + int ret2 = write(&m_scratch_buffer[0], dst_slot, 0, piece_size); + return ret1 != piece_size || ret2 != piece_size; } - void storage::swap_slots(int slot1, int slot2) + bool storage::swap_slots(int slot1, int slot2) { // the size of the target slot is the size of the piece - int piece_size = m_info->piece_length(); - int piece1_size = m_info->piece_size(slot2); - int piece2_size = m_info->piece_size(slot1); + int piece_size = m_files.piece_length(); + int piece1_size = m_files.piece_size(slot2); + int piece2_size = m_files.piece_size(slot1); m_scratch_buffer.resize(piece_size * 2); - read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true); - read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true); - write(&m_scratch_buffer[0], slot2, 0, piece1_size); - write(&m_scratch_buffer[piece_size], slot1, 0, piece2_size); + int ret1 = read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true); + int ret2 = read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true); + int ret3 = write(&m_scratch_buffer[0], slot2, 0, piece1_size); + int ret4 = write(&m_scratch_buffer[piece_size], slot1, 0, piece2_size); + return ret1 != piece1_size || ret2 != piece2_size + || ret3 != piece1_size || ret4 != piece2_size; } - void storage::swap_slots3(int slot1, int slot2, int slot3) + bool storage::swap_slots3(int slot1, int slot2, int slot3) { // the size of the target slot is the size of the piece - int piece_size = m_info->piece_length(); - int piece1_size = m_info->piece_size(slot2); - int piece2_size = m_info->piece_size(slot3); - int piece3_size = m_info->piece_size(slot1); + int piece_size = m_files.piece_length(); + int piece1_size = m_files.piece_size(slot2); + int piece2_size = m_files.piece_size(slot3); + int piece3_size = m_files.piece_size(slot1); m_scratch_buffer.resize(piece_size * 2); - read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true); - read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true); - write(&m_scratch_buffer[0], slot2, 0, piece1_size); - read_impl(&m_scratch_buffer[0], slot3, 0, piece3_size, true); - write(&m_scratch_buffer[piece_size], slot3, 0, piece2_size); - write(&m_scratch_buffer[0], slot1, 0, piece3_size); + int ret1 = read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true); + int ret2 = read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true); + int ret3 = write(&m_scratch_buffer[0], slot2, 0, piece1_size); + int ret4 = read_impl(&m_scratch_buffer[0], slot3, 0, piece3_size, true); + int ret5 = write(&m_scratch_buffer[piece_size], slot3, 0, piece2_size); + int ret6 = write(&m_scratch_buffer[0], slot1, 0, piece3_size); + return ret1 != piece1_size || ret2 != piece2_size + || ret3 != piece1_size || ret4 != piece3_size + || ret5 != piece2_size || ret6 != piece3_size; } - size_type storage::read( + int storage::read( char* buf , int slot , int offset @@ -803,7 +928,7 @@ namespace libtorrent return read_impl(buf, slot, offset, size, false); } - size_type storage::read_impl( + int storage::read_impl( char* buf , int slot , int offset @@ -811,25 +936,25 @@ namespace libtorrent , bool fill_zero) { TORRENT_ASSERT(buf != 0); - TORRENT_ASSERT(slot >= 0 && slot < m_info->num_pieces()); + TORRENT_ASSERT(slot >= 0 && slot < m_files.num_pieces()); TORRENT_ASSERT(offset >= 0); - TORRENT_ASSERT(offset < m_info->piece_size(slot)); + TORRENT_ASSERT(offset < m_files.piece_size(slot)); TORRENT_ASSERT(size > 0); #ifndef NDEBUG std::vector slices - = m_info->map_block(slot, offset, size, true); + = files().map_block(slot, offset, size); TORRENT_ASSERT(!slices.empty()); #endif - size_type start = slot * (size_type)m_info->piece_length() + offset; - TORRENT_ASSERT(start + size <= m_info->total_size()); + size_type start = slot * (size_type)m_files.piece_length() + offset; + TORRENT_ASSERT(start + size <= m_files.total_size()); // find the file iterator and file offset size_type file_offset = start; std::vector::const_iterator file_iter; - for (file_iter = m_info->begin_files(true);;) + for (file_iter = files().begin();;) { if (file_offset < file_iter->size) break; @@ -839,11 +964,21 @@ namespace libtorrent } int buf_pos = 0; - boost::shared_ptr in(m_files.open_file( - this, m_save_path / file_iter->path, file::in)); - + std::string error; + boost::shared_ptr in(m_pool.open_file( + this, m_save_path / file_iter->path, file::in + , error)); + if (!in) + { + set_error((m_save_path / file_iter->path).string(), error); + return -1; + } + if (!in->error().empty()) + { + set_error((m_save_path / file_iter->path).string(), in->error()); + return -1; + } TORRENT_ASSERT(file_offset < file_iter->size); - TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base); size_type new_pos = in->seek(file_offset + file_iter->file_base); @@ -851,7 +986,10 @@ namespace libtorrent { // the file was not big enough if (!fill_zero) - throw file_error("slot has no storage"); + { + set_error((m_save_path / file_iter->path).string(), "seek failed"); + return -1; + } std::memset(buf + buf_pos, 0, size - buf_pos); return size; } @@ -862,7 +1000,7 @@ namespace libtorrent #endif int left_to_read = size; - int slot_size = static_cast(m_info->piece_size(slot)); + int slot_size = static_cast(m_files.piece_size(slot)); if (offset + left_to_read > slot_size) left_to_read = slot_size - offset; @@ -887,7 +1025,7 @@ namespace libtorrent TORRENT_ASSERT(int(slices.size()) > counter); size_type slice_size = slices[counter].size; TORRENT_ASSERT(slice_size == read_bytes); - TORRENT_ASSERT(m_info->file_at(slices[counter].file_index, true).path + TORRENT_ASSERT(files().at(slices[counter].file_index).path == file_iter->path); #endif @@ -898,7 +1036,10 @@ namespace libtorrent // the file was not big enough if (actual_read > 0) buf_pos += actual_read; if (!fill_zero) - throw file_error("slot has no storage"); + { + set_error((m_save_path / file_iter->path).string(), "read failed"); + return -1; + } std::memset(buf + buf_pos, 0, size - buf_pos); return size; } @@ -920,16 +1061,36 @@ namespace libtorrent fs::path path = m_save_path / file_iter->path; file_offset = 0; - in = m_files.open_file( - this, path, file::in); - in->seek(file_iter->file_base); + std::string error; + in = m_pool.open_file( + this, path, file::in, error); + if (!in) + { + set_error(path.string(), error); + return -1; + } + if (!in->error().empty()) + { + set_error((m_save_path / file_iter->path).string(), in->error()); + return -1; + } + size_type pos = in->seek(file_iter->file_base); + if (pos != file_iter->file_base) + { + if (!fill_zero) + { + set_error((m_save_path / file_iter->path).string(), "seek failed"); + return -1; + } + std::memset(buf + buf_pos, 0, size - buf_pos); + return size; + } } } return result; } - // throws file_error if it fails to write - void storage::write( + int storage::write( const char* buf , int slot , int offset @@ -937,36 +1098,47 @@ namespace libtorrent { TORRENT_ASSERT(buf != 0); TORRENT_ASSERT(slot >= 0); - TORRENT_ASSERT(slot < m_info->num_pieces()); + TORRENT_ASSERT(slot < m_files.num_pieces()); TORRENT_ASSERT(offset >= 0); TORRENT_ASSERT(size > 0); #ifndef NDEBUG std::vector slices - = m_info->map_block(slot, offset, size, true); + = files().map_block(slot, offset, size); TORRENT_ASSERT(!slices.empty()); #endif - size_type start = slot * (size_type)m_info->piece_length() + offset; + size_type start = slot * (size_type)m_files.piece_length() + offset; // find the file iterator and file offset size_type file_offset = start; std::vector::const_iterator file_iter; - for (file_iter = m_info->begin_files(true);;) + for (file_iter = files().begin();;) { if (file_offset < file_iter->size) break; file_offset -= file_iter->size; ++file_iter; - TORRENT_ASSERT(file_iter != m_info->end_files(true)); + TORRENT_ASSERT(file_iter != files().end()); } fs::path p(m_save_path / file_iter->path); - boost::shared_ptr out = m_files.open_file( - this, p, file::out | file::in); + std::string error; + boost::shared_ptr out = m_pool.open_file( + this, p, file::out | file::in, error); + if (!out) + { + set_error(p.string(), error); + return -1; + } + if (!out->error().empty()) + { + set_error(p.string(), out->error()); + return -1; + } TORRENT_ASSERT(file_offset < file_iter->size); TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base); @@ -974,13 +1146,12 @@ namespace libtorrent if (pos != file_offset + file_iter->file_base) { - std::stringstream s; - s << "no storage for slot " << slot; - throw file_error(s.str()); + set_error((m_save_path / file_iter->path).string(), "seek failed"); + return -1; } int left_to_write = size; - int slot_size = static_cast(m_info->piece_size(slot)); + int slot_size = static_cast(m_files.piece_size(slot)); if (offset + left_to_write > slot_size) left_to_write = slot_size - offset; @@ -1004,7 +1175,7 @@ namespace libtorrent { TORRENT_ASSERT(int(slices.size()) > counter); TORRENT_ASSERT(slices[counter].size == write_bytes); - TORRENT_ASSERT(m_info->file_at(slices[counter].file_index, true).path + TORRENT_ASSERT(files().at(slices[counter].file_index).path == file_iter->path); TORRENT_ASSERT(buf_pos >= 0); @@ -1013,9 +1184,8 @@ namespace libtorrent if (written != write_bytes) { - std::stringstream s; - s << "no storage for slot " << slot; - throw file_error(s.str()); + set_error((m_save_path / file_iter->path).string(), "write failed"); + return -1; } left_to_write -= write_bytes; @@ -1032,35 +1202,56 @@ namespace libtorrent #endif ++file_iter; - TORRENT_ASSERT(file_iter != m_info->end_files(true)); + TORRENT_ASSERT(file_iter != files().end()); fs::path p = m_save_path / file_iter->path; file_offset = 0; - out = m_files.open_file( - this, p, file::out | file::in); + std::string error; + out = m_pool.open_file( + this, p, file::out | file::in, error); - out->seek(file_iter->file_base); + if (!out) + { + set_error(p.string(), error); + return -1; + } + if (!out->error().empty()) + { + set_error(p.string(), out->error()); + return -1; + } + + size_type pos = out->seek(file_iter->file_base); + + if (pos != file_iter->file_base) + { + set_error((m_save_path / file_iter->path).string(), "seek failed"); + return -1; + } } } + return size; } - storage_interface* default_storage_constructor(boost::intrusive_ptr ti + storage_interface* default_storage_constructor(file_storage const& fs , fs::path const& path, file_pool& fp) { - return new storage(ti, path, fp); + return new storage(fs, path, fp); } // -- piece_manager ----------------------------------------------------- piece_manager::piece_manager( boost::shared_ptr const& torrent - , boost::intrusive_ptr ti + , boost::intrusive_ptr info , fs::path const& save_path , file_pool& fp , disk_io_thread& io - , storage_constructor_type sc) - : m_storage(sc(ti, save_path, fp)) - , m_storage_mode(storage_mode_sparse) - , m_info(ti) + , storage_constructor_type sc + , storage_mode_t sm) + : m_info(info) + , m_files(m_info->files()) + , m_storage(sc(m_files, save_path, fp)) + , m_storage_mode(sm) , m_save_path(complete(save_path)) , m_state(state_none) , m_current_slot(0) @@ -1070,31 +1261,19 @@ namespace libtorrent , m_io_thread(io) , m_torrent(torrent) { -#ifndef NDEBUG - m_resume_data_verified = false; -#endif } piece_manager::~piece_manager() { } - void piece_manager::write_resume_data(entry& rd) const + void piece_manager::async_save_resume_data( + boost::function const& handler) { - m_storage->write_resume_data(rd); - } - - bool piece_manager::verify_resume_data(entry& rd, std::string& error) - { -#ifndef NDEBUG - m_resume_data_verified = true; -#endif - return m_storage->verify_resume_data(rd, error); - } - - void piece_manager::free_buffer(char* buf) - { - m_io_thread.free_buffer(buf); + disk_io_job j; + j.storage = this; + j.action = disk_io_job::save_resume_data; + m_io_thread.add_job(j, handler); } void piece_manager::async_release_files( @@ -1125,10 +1304,40 @@ namespace libtorrent m_io_thread.add_job(j, handler); } + void piece_manager::async_check_fastresume(lazy_entry const* resume_data + , boost::function const& handler) + { + TORRENT_ASSERT(resume_data != 0); + disk_io_job j; + j.storage = this; + j.action = disk_io_job::check_fastresume; + j.buffer = (char*)resume_data; + m_io_thread.add_job(j, handler); + } + + void piece_manager::async_rename_file(int index, std::string const& name + , boost::function const& handler) + { + disk_io_job j; + j.storage = this; + j.piece = index; + j.str = name; + j.action = disk_io_job::rename_file; + m_io_thread.add_job(j, handler); + } + + void piece_manager::async_check_files( + boost::function const& handler) + { + disk_io_job j; + j.storage = this; + j.action = disk_io_job::check_files; + m_io_thread.add_job(j, handler); + } + void piece_manager::async_read( peer_request const& r , boost::function const& handler - , char* buffer , int priority) { disk_io_job j; @@ -1137,20 +1346,28 @@ namespace libtorrent j.piece = r.piece; j.offset = r.start; j.buffer_size = r.length; - j.buffer = buffer; + j.buffer = 0; j.priority = priority; // if a buffer is not specified, only one block can be read // since that is the size of the pool allocator's buffers - TORRENT_ASSERT(r.length <= 16 * 1024 || buffer != 0); + TORRENT_ASSERT(r.length <= 16 * 1024); m_io_thread.add_job(j, handler); +#ifndef NDEBUG + boost::recursive_mutex::scoped_lock l(m_mutex); + // if this assert is hit, it suggests + // that check_files was not successful + TORRENT_ASSERT(slot_for(r.piece) >= 0); +#endif } void piece_manager::async_write( peer_request const& r - , char const* buffer + , disk_buffer_holder& buffer , boost::function const& handler) { TORRENT_ASSERT(r.length <= 16 * 1024); + // the buffer needs to be allocated through the io_thread + TORRENT_ASSERT(m_io_thread.is_disk_buffer(buffer.get())); disk_io_job j; j.storage = this; @@ -1158,10 +1375,9 @@ namespace libtorrent j.piece = r.piece; j.offset = r.start; j.buffer_size = r.length; - j.buffer = m_io_thread.allocate_buffer(); - if (j.buffer == 0) throw file_error("out of memory"); - std::memcpy(j.buffer, buffer, j.buffer_size); + j.buffer = buffer.get(); m_io_thread.add_job(j, handler); + buffer.release(); } void piece_manager::async_hash(int piece @@ -1194,30 +1410,31 @@ namespace libtorrent int slot = slot_for(piece); TORRENT_ASSERT(slot != has_no_slot); - return m_storage->hash_for_slot(slot, ph, m_info->piece_size(piece)); + return m_storage->hash_for_slot(slot, ph, m_files.piece_size(piece)); } - bool piece_manager::move_storage_impl(fs::path const& save_path) + int piece_manager::move_storage_impl(fs::path const& save_path) { if (m_storage->move_storage(save_path)) { m_save_path = fs::complete(save_path); - return true; + return 0; } - return false; + return -1; } - void piece_manager::export_piece_map( - std::vector& p, std::vector const& have) const + void piece_manager::write_resume_data(entry& rd) const { boost::recursive_mutex::scoped_lock lock(m_mutex); INVARIANT_CHECK; + m_storage->write_resume_data(rd); + if (m_storage_mode == storage_mode_compact) { - p.clear(); - p.reserve(m_info->num_pieces()); + entry::list_type& slots = rd["slots"].list(); + slots.clear(); std::vector::const_reverse_iterator last; for (last = m_slot_to_piece.rbegin(); last != m_slot_to_piece.rend(); ++last) @@ -1229,23 +1446,16 @@ namespace libtorrent m_slot_to_piece.begin(); i != last.base(); ++i) { - p.push_back((*i >= 0) ? *i : unassigned); - } - } - else - { - p.reserve(m_info->num_pieces()); - for (int i = 0; i < m_info->num_pieces(); ++i) - { - p.push_back(have[i] ? i : unassigned); + slots.push_back((*i >= 0) ? *i : unassigned); } } + + rd["allocation"] = m_storage_mode == storage_mode_sparse?"sparse" + :m_storage_mode == storage_mode_allocate?"full":"compact"; } void piece_manager::mark_failed(int piece_index) { - boost::recursive_mutex::scoped_lock lock(m_mutex); - INVARIANT_CHECK; if (m_storage_mode != storage_mode_compact) return; @@ -1259,49 +1469,7 @@ namespace libtorrent m_free_slots.push_back(slot_index); } - unsigned long piece_manager::piece_crc( - int slot_index - , int block_size - , piece_picker::block_info const* bi) - try - { - TORRENT_ASSERT(slot_index >= 0); - TORRENT_ASSERT(slot_index < m_info->num_pieces()); - TORRENT_ASSERT(block_size > 0); - - adler32_crc crc; - std::vector buf(block_size); - int num_blocks = static_cast(m_info->piece_size(slot_index)) / block_size; - int last_block_size = static_cast(m_info->piece_size(slot_index)) % block_size; - if (last_block_size == 0) last_block_size = block_size; - - for (int i = 0; i < num_blocks-1; ++i) - { - if (bi[i].state != piece_picker::block_info::state_finished) continue; - m_storage->read( - &buf[0] - , slot_index - , i * block_size - , block_size); - crc.update(&buf[0], block_size); - } - if (num_blocks > 0 && bi[num_blocks - 1].state == piece_picker::block_info::state_finished) - { - m_storage->read( - &buf[0] - , slot_index - , block_size * (num_blocks - 1) - , last_block_size); - crc.update(&buf[0], last_block_size); - } - return crc.final(); - } - catch (std::exception&) - { - return 0; - } - - size_type piece_manager::read_impl( + int piece_manager::read_impl( char* buf , int piece_index , int offset @@ -1314,7 +1482,7 @@ namespace libtorrent return m_storage->read(buf, slot, offset, size); } - void piece_manager::write_impl( + int piece_manager::write_impl( const char* buf , int piece_index , int offset @@ -1323,7 +1491,14 @@ namespace libtorrent TORRENT_ASSERT(buf); TORRENT_ASSERT(offset >= 0); TORRENT_ASSERT(size > 0); - TORRENT_ASSERT(piece_index >= 0 && piece_index < m_info->num_pieces()); + TORRENT_ASSERT(piece_index >= 0 && piece_index < m_files.num_pieces()); + + int slot = allocate_slot_for_piece(piece_index); + int ret = m_storage->write(buf, slot, offset, size); + // only save the partial hash if the write succeeds + if (ret != size) return ret; + +// std::ofstream out("partial_hash.log", std::ios::app); if (offset == 0) { @@ -1331,41 +1506,76 @@ namespace libtorrent TORRENT_ASSERT(ph.offset == 0); ph.offset = size; ph.h.update(buf, size); +/* + out << time_now_string() << " NEW [" + " s: " << this + << " p: " << piece_index + << " off: " << offset + << " size: " << size + << " entries: " << m_piece_hasher.size() + << " ]" << std::endl; +*/ } else { std::map::iterator i = m_piece_hasher.find(piece_index); if (i != m_piece_hasher.end()) { +#ifndef NDEBUG TORRENT_ASSERT(i->second.offset > 0); - TORRENT_ASSERT(offset >= i->second.offset); + int hash_offset = i->second.offset; + TORRENT_ASSERT(offset >= hash_offset); +#endif if (offset == i->second.offset) { +/* + out << time_now_string() << " UPDATING [" + " s: " << this + << " p: " << piece_index + << " off: " << offset + << " size: " << size + << " entries: " << m_piece_hasher.size() + << " ]" << std::endl; +*/ i->second.offset += size; i->second.h.update(buf, size); } +/* else + { + out << time_now_string() << " SKIPPING (out of order) [" + " s: " << this + << " p: " << piece_index + << " off: " << offset + << " size: " << size + << " entries: " << m_piece_hasher.size() + << " ]" << std::endl; + } +*/ } +/* else + { + out << time_now_string() << " SKIPPING (no entry) [" + " s: " << this + << " p: " << piece_index + << " off: " << offset + << " size: " << size + << " entries: " << m_piece_hasher.size() + << " ]" << std::endl; } +*/ } - int slot = allocate_slot_for_piece(piece_index); - m_storage->write(buf, slot, offset, size); + return ret; } int piece_manager::identify_data( const std::vector& piece_data - , int current_slot - , std::vector& have_pieces - , int& num_pieces - , const std::multimap& hash_to_piece - , boost::recursive_mutex& mutex) + , int current_slot) { // INVARIANT_CHECK; - TORRENT_ASSERT((int)have_pieces.size() == m_info->num_pieces()); - - const int piece_size = static_cast(m_info->piece_length()); - const int last_piece_size = static_cast(m_info->piece_size( - m_info->num_pieces() - 1)); + const int piece_size = static_cast(m_files.piece_length()); + const int last_piece_size = static_cast(m_files.piece_size( + m_files.num_pieces() - 1)); TORRENT_ASSERT((int)piece_data.size() >= last_piece_size); @@ -1392,8 +1602,8 @@ namespace libtorrent map_iter end2; // makes the lookups for the small digest and the large digest - boost::tie(begin1, end1) = hash_to_piece.equal_range(small_hash); - boost::tie(begin2, end2) = hash_to_piece.equal_range(large_hash); + boost::tie(begin1, end1) = m_hash_to_piece.equal_range(small_hash); + boost::tie(begin2, end2) = m_hash_to_piece.equal_range(large_hash); // copy all potential piece indices into this vector std::vector matching_pieces; @@ -1419,15 +1629,11 @@ namespace libtorrent // we will assume that the piece is in the right place const int piece_index = current_slot; - // lock because we're writing to have_pieces - boost::recursive_mutex::scoped_lock l(mutex); - - if (have_pieces[piece_index]) + int other_slot = m_piece_to_slot[piece_index]; + if (other_slot >= 0) { // we have already found a piece with // this index. - int other_slot = m_piece_to_slot[piece_index]; - TORRENT_ASSERT(other_slot >= 0); // take one of the other matching pieces // that hasn't already been assigned @@ -1435,18 +1641,15 @@ namespace libtorrent for (std::vector::iterator i = matching_pieces.begin(); i != matching_pieces.end(); ++i) { - if (have_pieces[*i] || *i == piece_index) continue; + if (m_piece_to_slot[*i] >= 0 || *i == piece_index) continue; other_piece = *i; break; } if (other_piece >= 0) { // replace the old slot with 'other_piece' - TORRENT_ASSERT(have_pieces[other_piece] == false); - have_pieces[other_piece] = true; m_slot_to_piece[other_slot] = other_piece; m_piece_to_slot[other_piece] = other_slot; - ++num_pieces; } else { @@ -1462,19 +1665,9 @@ namespace libtorrent TORRENT_ASSERT(m_piece_to_slot[piece_index] != current_slot); TORRENT_ASSERT(m_piece_to_slot[piece_index] >= 0); m_piece_to_slot[piece_index] = has_no_slot; -#ifndef NDEBUG - // to make the assert happy, a few lines down - have_pieces[piece_index] = false; -#endif - } - else - { - ++num_pieces; } - TORRENT_ASSERT(have_pieces[piece_index] == false); TORRENT_ASSERT(m_piece_to_slot[piece_index] == has_no_slot); - have_pieces[piece_index] = true; return piece_index; } @@ -1485,21 +1678,14 @@ namespace libtorrent for (std::vector::iterator i = matching_pieces.begin(); i != matching_pieces.end(); ++i) { - if (have_pieces[*i]) continue; + if (m_piece_to_slot[*i] >= 0) continue; free_piece = *i; break; } if (free_piece >= 0) { - // lock because we're writing to have_pieces - boost::recursive_mutex::scoped_lock l(mutex); - - TORRENT_ASSERT(have_pieces[free_piece] == false); TORRENT_ASSERT(m_piece_to_slot[free_piece] == has_no_slot); - have_pieces[free_piece] = true; - ++num_pieces; - return free_piece; } else @@ -1509,147 +1695,298 @@ namespace libtorrent } } + int piece_manager::check_no_fastresume(std::string& error) + { + file_storage::iterator i = m_files.begin(); + file_storage::iterator end = m_files.end(); + + for (; i != end; ++i) + { + bool file_exists = false; + fs::path f = m_save_path / i->path; +#ifndef BOOST_NO_EXCEPTIONS + try + { +#endif +#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 + file_exists = exists_win(f); +#elif TORRENT_USE_WPATH + fs::wpath wf = safe_convert(f.string()); + file_exists = exists(wf); +#else + file_exists = exists(f); +#endif +#ifndef BOOST_NO_EXCEPTIONS + } + catch (std::exception& e) + { + error = f.string(); + error += ": "; + error += e.what(); + return fatal_disk_error; + } +#endif + if (file_exists && i->size > 0) + { + m_state = state_full_check; + m_piece_to_slot.clear(); + m_piece_to_slot.resize(m_files.num_pieces(), has_no_slot); + m_slot_to_piece.clear(); + m_slot_to_piece.resize(m_files.num_pieces(), unallocated); + if (m_storage_mode == storage_mode_compact) + { + m_unallocated_slots.clear(); + m_free_slots.clear(); + } + return need_full_check; + } + } + + if (m_storage_mode == storage_mode_compact) + { + // in compact mode without checking, we need to + // populate the unallocated list + TORRENT_ASSERT(m_unallocated_slots.empty()); + for (int i = 0, end(m_files.num_pieces()); i < end; ++i) + m_unallocated_slots.push_back(i); + m_piece_to_slot.clear(); + m_piece_to_slot.resize(m_files.num_pieces(), has_no_slot); + m_slot_to_piece.clear(); + m_slot_to_piece.resize(m_files.num_pieces(), unallocated); + } + + return check_init_storage(error); + } + + int piece_manager::check_init_storage(std::string& error) + { + if (m_storage->initialize(m_storage_mode == storage_mode_allocate)) + { + error = m_storage->error(); + m_storage->clear_error(); + return fatal_disk_error; + } + m_state = state_finished; + buffer().swap(m_scratch_buffer); + buffer().swap(m_scratch_buffer2); + if (m_storage_mode != storage_mode_compact) + { + // if no piece is out of place + // since we're in full allocation mode, we can + // forget the piece allocation tables + std::vector().swap(m_piece_to_slot); + std::vector().swap(m_slot_to_piece); + std::vector().swap(m_free_slots); + std::vector().swap(m_unallocated_slots); + } + return no_error; + } + // check if the fastresume data is up to date // if it is, use it and return true. If it // isn't return false and the full check // will be run - bool piece_manager::check_fastresume( - aux::piece_checker_data& data - , std::vector& pieces - , int& num_pieces, storage_mode_t storage_mode - , std::string& error_msg) + int piece_manager::check_fastresume( + lazy_entry const& rd, std::string& error) { boost::recursive_mutex::scoped_lock lock(m_mutex); INVARIANT_CHECK; - TORRENT_ASSERT(m_info->piece_length() > 0); + TORRENT_ASSERT(m_files.piece_length() > 0); - m_storage_mode = storage_mode; + // if we don't have any resume data, return + if (rd.type() == lazy_entry::none_t) return check_no_fastresume(error); - // This will corrupt the storage - // use while debugging to find - // states that cannot be scanned - // by check_pieces. -// m_storage->shuffle(); + if (rd.type() != lazy_entry::dict_t) + { + error = "invalid fastresume data (not a dictionary)"; + return check_no_fastresume(error); + } - m_piece_to_slot.resize(m_info->num_pieces(), has_no_slot); - m_slot_to_piece.resize(m_info->num_pieces(), unallocated); - TORRENT_ASSERT(m_free_slots.empty()); - TORRENT_ASSERT(m_unallocated_slots.empty()); + int block_size = (std::min)(16 * 1024, m_files.piece_length()); + int blocks_per_piece = rd.dict_find_int_value("blocks per piece", -1); + if (blocks_per_piece != -1 + && blocks_per_piece != m_files.piece_length() / block_size) + { + error = "invalid 'blocks per piece' entry"; + return check_no_fastresume(error); + } + + storage_mode_t storage_mode = storage_mode_compact; + if (rd.dict_find_string_value("allocation") != "compact") + storage_mode = storage_mode_sparse; // assume no piece is out of place (i.e. in a slot // other than the one it should be in) bool out_of_place = false; - - pieces.clear(); - pieces.resize(m_info->num_pieces(), false); - num_pieces = 0; - // if we have fast-resume info - // use it instead of doing the actual checking - if (!data.piece_map.empty() - && int(data.piece_map.size()) <= m_info->num_pieces()) + // if we don't have a piece map, we need the slots + // if we're in compact mode, we also need the slots map + if (storage_mode == storage_mode_compact || rd.dict_find("pieces") == 0) { - TORRENT_ASSERT(m_resume_data_verified); - for (int i = 0; i < (int)data.piece_map.size(); ++i) + // read slots map + lazy_entry const* slots = rd.dict_find_list("slots"); + if (slots == 0) { - m_slot_to_piece[i] = data.piece_map[i]; - if (data.piece_map[i] >= 0) - { - if (data.piece_map[i] != i) out_of_place = true; - m_piece_to_slot[data.piece_map[i]] = i; - int found_piece = data.piece_map[i]; + error = "missing slot list"; + return check_no_fastresume(error); + } - // if the piece is not in the unfinished list - // we have all of it - if (std::find_if( - data.unfinished_pieces.begin() - , data.unfinished_pieces.end() - , piece_picker::has_index(found_piece)) - == data.unfinished_pieces.end()) - { - ++num_pieces; - pieces[found_piece] = true; - } - } - else if (data.piece_map[i] == unassigned) - { - if (m_storage_mode == storage_mode_compact) - m_free_slots.push_back(i); - } - else - { - TORRENT_ASSERT(data.piece_map[i] == unallocated); - if (m_storage_mode == storage_mode_compact) - m_unallocated_slots.push_back(i); - } + if ((int)slots->list_size() > m_files.num_pieces()) + { + error = "file has more slots than torrent (slots: " + + boost::lexical_cast(slots->list_size()) + " size: " + + boost::lexical_cast(m_files.num_pieces()) + " )"; + return check_no_fastresume(error); } if (m_storage_mode == storage_mode_compact) { - m_unallocated_slots.reserve(int(m_info->num_pieces() - data.piece_map.size())); - for (int i = (int)data.piece_map.size(); i < (int)m_info->num_pieces(); ++i) + int num_pieces = int(m_files.num_pieces()); + m_slot_to_piece.resize(num_pieces, unallocated); + m_piece_to_slot.resize(num_pieces, has_no_slot); + for (int i = 0; i < slots->list_size(); ++i) { - m_unallocated_slots.push_back(i); - } - if (m_unallocated_slots.empty()) - { - switch_to_full_mode(); + lazy_entry const* e = slots->list_at(i); + if (e->type() != lazy_entry::int_t) + { + error = "invalid entry type in slot list"; + return check_no_fastresume(error); + } + + int index = int(e->int_value()); + if (index >= num_pieces || index < -2) + { + error = "too high index number in slot map (index: " + + boost::lexical_cast(index) + " size: " + + boost::lexical_cast(num_pieces) + ")"; + return check_no_fastresume(error); + } + if (index >= 0) + { + m_slot_to_piece[i] = index; + m_piece_to_slot[index] = i; + if (i != index) out_of_place = true; + } + else if (index == unassigned) + { + if (m_storage_mode == storage_mode_compact) + m_free_slots.push_back(i); + } + else + { + TORRENT_ASSERT(index == unallocated); + if (m_storage_mode == storage_mode_compact) + m_unallocated_slots.push_back(i); + } } } else { - if (!out_of_place) + for (int i = 0; i < slots->list_size(); ++i) { - // if no piece is out of place - // since we're in full allocation mode, we can - // forget the piece allocation tables + lazy_entry const* e = slots->list_at(i); + if (e->type() != lazy_entry::int_t) + { + error = "invalid entry type in slot list"; + return check_no_fastresume(error); + } - std::vector().swap(m_piece_to_slot); - std::vector().swap(m_slot_to_piece); - m_state = state_create_files; - return false; + int index = int(e->int_value()); + if (index != i && index >= 0) + { + error = "invalid slot index"; + return check_no_fastresume(error); + } } - else + } + + if (!m_storage->verify_resume_data(rd, error)) + return check_no_fastresume(error); + + // This will corrupt the storage + // use while debugging to find + // states that cannot be scanned + // by check_pieces. + // m_storage->shuffle(); + + if (m_storage_mode == storage_mode_compact) + { + if (m_unallocated_slots.empty()) switch_to_full_mode(); + } + else + { + TORRENT_ASSERT(m_free_slots.empty()); + TORRENT_ASSERT(m_unallocated_slots.empty()); + + if (out_of_place) { // in this case we're in full allocation mode, but // we're resuming a compact allocated storage m_state = state_expand_pieces; m_current_slot = 0; - error_msg = "pieces needs to be reordered"; - return false; + error = "pieces needs to be reordered"; + return need_full_check; } } - m_state = state_create_files; - return false; + } + else if (m_storage_mode == storage_mode_compact) + { + // read piece map + lazy_entry const* pieces = rd.dict_find("pieces"); + if (pieces == 0 || pieces->type() != lazy_entry::string_t) + { + error = "missing pieces entry"; + return check_no_fastresume(error); + } + + if ((int)pieces->string_length() != m_files.num_pieces()) + { + error = "file has more slots than torrent (slots: " + + boost::lexical_cast(pieces->string_length()) + " size: " + + boost::lexical_cast(m_files.num_pieces()) + " )"; + return check_no_fastresume(error); + } + + int num_pieces = int(m_files.num_pieces()); + m_slot_to_piece.resize(num_pieces, unallocated); + m_piece_to_slot.resize(num_pieces, has_no_slot); + char const* have_pieces = pieces->string_ptr(); + for (int i = 0; i < num_pieces; ++i) + { + if (have_pieces[i] & 1) + { + m_slot_to_piece[i] = i; + m_piece_to_slot[i] = i; + } + else + { + m_free_slots.push_back(i); + } + } + if (m_unallocated_slots.empty()) switch_to_full_mode(); } - m_state = state_full_check; - return false; + return check_init_storage(error); } /* state chart: - check_fastresume() - - | | - | v + check_fastresume() ----------+ + | + | | | + | v v | +------------+ +---------------+ | | full_check |-->| expand_pieses | | +------------+ +---------------+ | | | | v | | +--------------+ | - +->| create_files | <------+ + +->| finished | <------+ +--------------+ - | - v - +----------+ - | finished | - +----------+ */ @@ -1659,22 +1996,12 @@ namespace libtorrent // the second return value is the progress the // file check is at. 0 is nothing done, and 1 // is finished - std::pair piece_manager::check_files( - std::vector& pieces, int& num_pieces, boost::recursive_mutex& mutex) + int piece_manager::check_files(int& current_slot, int& have_piece, std::string& error) { -#ifndef NDEBUG - boost::recursive_mutex::scoped_lock l_(mutex); - TORRENT_ASSERT(num_pieces == std::count(pieces.begin(), pieces.end(), true)); - l_.unlock(); -#endif - - if (m_state == state_create_files) - { - m_storage->initialize(m_storage_mode == storage_mode_allocate); - m_state = state_finished; - return std::make_pair(true, 1.f); - } + TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces()); + current_slot = m_current_slot; + have_piece = -1; if (m_state == state_expand_pieces) { INVARIANT_CHECK; @@ -1688,45 +2015,52 @@ namespace libtorrent if (other_piece >= 0) { if (m_scratch_buffer2.empty()) - m_scratch_buffer2.resize(m_info->piece_length()); + m_scratch_buffer2.resize(m_files.piece_length()); - m_storage->read(&m_scratch_buffer2[0], piece, 0, m_info->piece_size(other_piece)); + int piece_size = m_files.piece_size(other_piece); + if (m_storage->read(&m_scratch_buffer2[0], piece, 0, piece_size) + != piece_size) + { + error = m_storage->error(); + m_storage->clear_error(); + return fatal_disk_error; + } m_scratch_piece = other_piece; m_piece_to_slot[other_piece] = unassigned; } // the slot where this piece belongs is // free. Just move the piece there. - m_storage->write(&m_scratch_buffer[0], piece, 0, m_info->piece_size(piece)); + int piece_size = m_files.piece_size(piece); + if (m_storage->write(&m_scratch_buffer[0], piece, 0, piece_size) != piece_size) + { + error = m_storage->error(); + m_storage->clear_error(); + return fatal_disk_error; + } m_piece_to_slot[piece] = piece; m_slot_to_piece[piece] = piece; if (other_piece >= 0) m_scratch_buffer.swap(m_scratch_buffer2); - return std::make_pair(false, (float)m_current_slot / m_info->num_pieces()); + return need_full_check; } - while (m_current_slot < m_info->num_pieces() + while (m_current_slot < m_files.num_pieces() && (m_slot_to_piece[m_current_slot] == m_current_slot || m_slot_to_piece[m_current_slot] < 0)) { ++m_current_slot; } - if (m_current_slot == m_info->num_pieces()) + if (m_current_slot == m_files.num_pieces()) { - m_state = state_create_files; - buffer().swap(m_scratch_buffer); - buffer().swap(m_scratch_buffer2); - if (m_storage_mode != storage_mode_compact) - { - std::vector().swap(m_piece_to_slot); - std::vector().swap(m_slot_to_piece); - } - return std::make_pair(false, 1.f); + return check_init_storage(error); } + TORRENT_ASSERT(m_current_slot < m_files.num_pieces()); + int piece = m_slot_to_piece[m_current_slot]; TORRENT_ASSERT(piece >= 0); int other_piece = m_slot_to_piece[piece]; @@ -1736,9 +2070,15 @@ namespace libtorrent // where this one goes. Store it in the scratch // buffer until next iteration. if (m_scratch_buffer.empty()) - m_scratch_buffer.resize(m_info->piece_length()); + m_scratch_buffer.resize(m_files.piece_length()); - m_storage->read(&m_scratch_buffer[0], piece, 0, m_info->piece_size(other_piece)); + int piece_size = m_files.piece_size(other_piece); + if (m_storage->read(&m_scratch_buffer[0], piece, 0, piece_size) != piece_size) + { + error = m_storage->error(); + m_storage->clear_error(); + return fatal_disk_error; + } m_scratch_piece = other_piece; m_piece_to_slot[other_piece] = unassigned; } @@ -1750,253 +2090,24 @@ namespace libtorrent m_slot_to_piece[m_current_slot] = unassigned; m_slot_to_piece[piece] = piece; - return std::make_pair(false, (float)m_current_slot / m_info->num_pieces()); + return need_full_check; } TORRENT_ASSERT(m_state == state_full_check); - // ------------------------ - // DO THE FULL CHECK - // ------------------------ + bool skip = check_one_piece(have_piece); + TORRENT_ASSERT(m_current_slot <= m_files.num_pieces()); - try + if (skip) { - if (m_info->num_pieces() == 0) - { - m_state = state_create_files; - return std::make_pair(false, 1.f); - } - - // initialization for the full check - if (m_hash_to_piece.empty()) - { - for (int i = 0; i < m_info->num_pieces(); ++i) - { - m_hash_to_piece.insert(std::make_pair(m_info->hash_for_piece(i), i)); - } - boost::recursive_mutex::scoped_lock l(mutex); - std::fill(pieces.begin(), pieces.end(), false); - num_pieces = 0; - } - - m_piece_data.resize(int(m_info->piece_length())); - int piece_size = int(m_info->piece_size(m_current_slot)); - int num_read = int(m_storage->read(&m_piece_data[0] - , m_current_slot, 0, piece_size)); - - // if the file is incomplete, skip the rest of it - if (num_read != piece_size) - throw file_error(""); - - int piece_index = identify_data(m_piece_data, m_current_slot - , pieces, num_pieces, m_hash_to_piece, mutex); - - if (piece_index != m_current_slot - && piece_index >= 0) - m_out_of_place = true; - - TORRENT_ASSERT(num_pieces == std::count(pieces.begin(), pieces.end(), true)); - TORRENT_ASSERT(piece_index == unassigned || piece_index >= 0); - - const bool this_should_move = piece_index >= 0 && m_slot_to_piece[piece_index] != unallocated; - const bool other_should_move = m_piece_to_slot[m_current_slot] != has_no_slot; - - // check if this piece should be swapped with any other slot - // this section will ensure that the storage is correctly sorted - // libtorrent will never leave the storage in a state that - // requires this sorting, but other clients may. - - // example of worst case: - // | m_current_slot = 5 - // V - // +---+- - - +---+- - - +---+- - - // | x | | 5 | | 3 | <- piece data in slots - // +---+- - - +---+- - - +---+- - - // 3 y 5 <- slot index - - // in this example, the data in the m_current_slot (5) - // is piece 3. It has to be moved into slot 3. The data - // in slot y (piece 5) should be moved into the m_current_slot. - // and the data in slot 3 (piece x) should be moved to slot y. - - // there are three possible cases. - // 1. There's another piece that should be placed into this slot - // 2. This piece should be placed into another slot. - // 3. There's another piece that should be placed into this slot - // and this piece should be placed into another slot - - // swap piece_index with this slot - - // case 1 - if (this_should_move && !other_should_move) - { - TORRENT_ASSERT(piece_index != m_current_slot); - - const int other_slot = piece_index; - TORRENT_ASSERT(other_slot >= 0); - int other_piece = m_slot_to_piece[other_slot]; - - m_slot_to_piece[other_slot] = piece_index; - m_slot_to_piece[m_current_slot] = other_piece; - m_piece_to_slot[piece_index] = piece_index; - if (other_piece >= 0) m_piece_to_slot[other_piece] = m_current_slot; - - if (other_piece == unassigned) - { - std::vector::iterator i = - std::find(m_free_slots.begin(), m_free_slots.end(), other_slot); - TORRENT_ASSERT(i != m_free_slots.end()); - if (m_storage_mode == storage_mode_compact) - { - m_free_slots.erase(i); - m_free_slots.push_back(m_current_slot); - } - } - - if (other_piece >= 0) - m_storage->swap_slots(other_slot, m_current_slot); - else - m_storage->move_slot(m_current_slot, other_slot); - - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - // case 2 - else if (!this_should_move && other_should_move) - { - TORRENT_ASSERT(piece_index != m_current_slot); - - const int other_piece = m_current_slot; - const int other_slot = m_piece_to_slot[other_piece]; - TORRENT_ASSERT(other_slot >= 0); - - m_slot_to_piece[m_current_slot] = other_piece; - m_slot_to_piece[other_slot] = piece_index; - m_piece_to_slot[other_piece] = m_current_slot; - - if (piece_index == unassigned - && m_storage_mode == storage_mode_compact) - m_free_slots.push_back(other_slot); - - if (piece_index >= 0) - { - m_piece_to_slot[piece_index] = other_slot; - m_storage->swap_slots(other_slot, m_current_slot); - } - else - { - m_storage->move_slot(other_slot, m_current_slot); - } - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - else if (this_should_move && other_should_move) - { - TORRENT_ASSERT(piece_index != m_current_slot); - TORRENT_ASSERT(piece_index >= 0); - - const int piece1 = m_slot_to_piece[piece_index]; - const int piece2 = m_current_slot; - const int slot1 = piece_index; - const int slot2 = m_piece_to_slot[piece2]; - - TORRENT_ASSERT(slot1 >= 0); - TORRENT_ASSERT(slot2 >= 0); - TORRENT_ASSERT(piece2 >= 0); - - if (slot1 == slot2) - { - // this means there are only two pieces involved in the swap - TORRENT_ASSERT(piece1 >= 0); - - // movement diagram: - // +-------------------------------+ - // | | - // +--> slot1 --> m_current_slot --+ - - m_slot_to_piece[slot1] = piece_index; - m_slot_to_piece[m_current_slot] = piece1; - - m_piece_to_slot[piece_index] = slot1; - m_piece_to_slot[piece1] = m_current_slot; - - TORRENT_ASSERT(piece1 == m_current_slot); - TORRENT_ASSERT(piece_index == slot1); - - m_storage->swap_slots(m_current_slot, slot1); - - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - else - { - TORRENT_ASSERT(slot1 != slot2); - TORRENT_ASSERT(piece1 != piece2); - - // movement diagram: - // +-----------------------------------------+ - // | | - // +--> slot1 --> slot2 --> m_current_slot --+ - - m_slot_to_piece[slot1] = piece_index; - m_slot_to_piece[slot2] = piece1; - m_slot_to_piece[m_current_slot] = piece2; - - m_piece_to_slot[piece_index] = slot1; - m_piece_to_slot[m_current_slot] = piece2; - - if (piece1 == unassigned) - { - std::vector::iterator i = - std::find(m_free_slots.begin(), m_free_slots.end(), slot1); - TORRENT_ASSERT(i != m_free_slots.end()); - if (m_storage_mode == storage_mode_compact) - { - m_free_slots.erase(i); - m_free_slots.push_back(slot2); - } - } - - if (piece1 >= 0) - { - m_piece_to_slot[piece1] = slot2; - m_storage->swap_slots3(m_current_slot, slot1, slot2); - } - else - { - m_storage->move_slot(m_current_slot, slot1); - m_storage->move_slot(slot2, m_current_slot); - } - - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - } - else - { - TORRENT_ASSERT(m_piece_to_slot[m_current_slot] == has_no_slot || piece_index != m_current_slot); - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unallocated); - TORRENT_ASSERT(piece_index == unassigned || m_piece_to_slot[piece_index] == has_no_slot); - - // the slot was identified as piece 'piece_index' - if (piece_index != unassigned) - m_piece_to_slot[piece_index] = m_current_slot; - else if (m_storage_mode == storage_mode_compact) - m_free_slots.push_back(m_current_slot); - - m_slot_to_piece[m_current_slot] = piece_index; - - TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - } - catch (file_error&) - { - // find the file that failed, and skip all the blocks in that file + clear_error(); + // skip means that the piece we checked failed to be read from disk + // completely. We should skip all pieces belonging to that file. + // find the file that failed, and skip all the pieces in that file size_type file_offset = 0; - size_type current_offset = size_type(m_current_slot) * m_info->piece_length(); - for (torrent_info::file_iterator i = m_info->begin_files(true); - i != m_info->end_files(true); ++i) + size_type current_offset = size_type(m_current_slot) * m_files.piece_length(); + for (file_storage::iterator i = m_files.begin() + , end(m_files.end()); i != end; ++i) { file_offset += i->size; if (file_offset > current_offset) break; @@ -2004,8 +2115,8 @@ namespace libtorrent TORRENT_ASSERT(file_offset > current_offset); int skip_blocks = static_cast( - (file_offset - current_offset + m_info->piece_length() - 1) - / m_info->piece_length()); + (file_offset - current_offset + m_files.piece_length() - 1) + / m_files.piece_length()); if (m_storage_mode == storage_mode_compact) { @@ -2018,12 +2129,15 @@ namespace libtorrent // current slot will increase by one at the end of the for-loop too m_current_slot += skip_blocks - 1; + TORRENT_ASSERT(m_current_slot <= m_files.num_pieces()); } - ++m_current_slot; - if (m_current_slot >= m_info->num_pieces()) + ++m_current_slot; + current_slot = m_current_slot; + + if (m_current_slot >= m_files.num_pieces()) { - TORRENT_ASSERT(m_current_slot == m_info->num_pieces()); + TORRENT_ASSERT(m_current_slot == m_files.num_pieces()); // clear the memory we've been using std::vector().swap(m_piece_data); @@ -2039,8 +2153,7 @@ namespace libtorrent std::vector().swap(m_piece_to_slot); std::vector().swap(m_slot_to_piece); - m_state = state_create_files; - return std::make_pair(false, 1.f); + return check_init_storage(error); } else { @@ -2048,25 +2161,257 @@ namespace libtorrent // we're resuming a compact allocated storage m_state = state_expand_pieces; m_current_slot = 0; - return std::make_pair(false, 0.f); + current_slot = m_current_slot; + return need_full_check; } } else if (m_unallocated_slots.empty()) { switch_to_full_mode(); } - m_state = state_create_files; + return check_init_storage(error); + } + return need_full_check; + } -#ifndef NDEBUG - boost::recursive_mutex::scoped_lock l(mutex); - TORRENT_ASSERT(num_pieces == std::count(pieces.begin(), pieces.end(), true)); -#endif - return std::make_pair(false, 1.f); + bool piece_manager::check_one_piece(int& have_piece) + { + // ------------------------ + // DO THE FULL CHECK + // ------------------------ + + TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces()); + TORRENT_ASSERT(int(m_slot_to_piece.size()) == m_files.num_pieces()); + TORRENT_ASSERT(have_piece == -1); + + // initialization for the full check + if (m_hash_to_piece.empty()) + { + for (int i = 0; i < m_files.num_pieces(); ++i) + m_hash_to_piece.insert(std::make_pair(m_info->hash_for_piece(i), i)); } - TORRENT_ASSERT(num_pieces == std::count(pieces.begin(), pieces.end(), true)); + m_piece_data.resize(int(m_files.piece_length())); + int piece_size = m_files.piece_size(m_current_slot); + int num_read = m_storage->read(&m_piece_data[0] + , m_current_slot, 0, piece_size); - return std::make_pair(false, (float)m_current_slot / m_info->num_pieces()); + // if the file is incomplete, skip the rest of it + if (num_read != piece_size) + return true; + + int piece_index = identify_data(m_piece_data, m_current_slot); + + if (piece_index >= 0) have_piece = piece_index; + + if (piece_index != m_current_slot + && piece_index >= 0) + m_out_of_place = true; + + TORRENT_ASSERT(piece_index == unassigned || piece_index >= 0); + + const bool this_should_move = piece_index >= 0 && m_slot_to_piece[piece_index] != unallocated; + const bool other_should_move = m_piece_to_slot[m_current_slot] != has_no_slot; + + // check if this piece should be swapped with any other slot + // this section will ensure that the storage is correctly sorted + // libtorrent will never leave the storage in a state that + // requires this sorting, but other clients may. + + // example of worst case: + // | m_current_slot = 5 + // V + // +---+- - - +---+- - - +---+- - + // | x | | 5 | | 3 | <- piece data in slots + // +---+- - - +---+- - - +---+- - + // 3 y 5 <- slot index + + // in this example, the data in the m_current_slot (5) + // is piece 3. It has to be moved into slot 3. The data + // in slot y (piece 5) should be moved into the m_current_slot. + // and the data in slot 3 (piece x) should be moved to slot y. + + // there are three possible cases. + // 1. There's another piece that should be placed into this slot + // 2. This piece should be placed into another slot. + // 3. There's another piece that should be placed into this slot + // and this piece should be placed into another slot + + // swap piece_index with this slot + + // case 1 + if (this_should_move && !other_should_move) + { + TORRENT_ASSERT(piece_index != m_current_slot); + + const int other_slot = piece_index; + TORRENT_ASSERT(other_slot >= 0); + int other_piece = m_slot_to_piece[other_slot]; + + m_slot_to_piece[other_slot] = piece_index; + m_slot_to_piece[m_current_slot] = other_piece; + m_piece_to_slot[piece_index] = piece_index; + if (other_piece >= 0) m_piece_to_slot[other_piece] = m_current_slot; + + if (other_piece == unassigned) + { + std::vector::iterator i = + std::find(m_free_slots.begin(), m_free_slots.end(), other_slot); + TORRENT_ASSERT(i != m_free_slots.end()); + if (m_storage_mode == storage_mode_compact) + { + m_free_slots.erase(i); + m_free_slots.push_back(m_current_slot); + } + } + + bool ret = false; + if (other_piece >= 0) + ret |= m_storage->swap_slots(other_slot, m_current_slot); + else + ret |= m_storage->move_slot(m_current_slot, other_slot); + + if (ret) return true; + + TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned + || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); + } + // case 2 + else if (!this_should_move && other_should_move) + { + TORRENT_ASSERT(piece_index != m_current_slot); + + const int other_piece = m_current_slot; + const int other_slot = m_piece_to_slot[other_piece]; + TORRENT_ASSERT(other_slot >= 0); + + m_slot_to_piece[m_current_slot] = other_piece; + m_slot_to_piece[other_slot] = piece_index; + m_piece_to_slot[other_piece] = m_current_slot; + + if (piece_index == unassigned + && m_storage_mode == storage_mode_compact) + m_free_slots.push_back(other_slot); + + bool ret = false; + if (piece_index >= 0) + { + m_piece_to_slot[piece_index] = other_slot; + ret |= m_storage->swap_slots(other_slot, m_current_slot); + } + else + { + ret |= m_storage->move_slot(other_slot, m_current_slot); + + } + if (ret) return true; + + TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned + || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); + } + else if (this_should_move && other_should_move) + { + TORRENT_ASSERT(piece_index != m_current_slot); + TORRENT_ASSERT(piece_index >= 0); + + const int piece1 = m_slot_to_piece[piece_index]; + const int piece2 = m_current_slot; + const int slot1 = piece_index; + const int slot2 = m_piece_to_slot[piece2]; + + TORRENT_ASSERT(slot1 >= 0); + TORRENT_ASSERT(slot2 >= 0); + TORRENT_ASSERT(piece2 >= 0); + + if (slot1 == slot2) + { + // this means there are only two pieces involved in the swap + TORRENT_ASSERT(piece1 >= 0); + + // movement diagram: + // +-------------------------------+ + // | | + // +--> slot1 --> m_current_slot --+ + + m_slot_to_piece[slot1] = piece_index; + m_slot_to_piece[m_current_slot] = piece1; + + m_piece_to_slot[piece_index] = slot1; + m_piece_to_slot[piece1] = m_current_slot; + + TORRENT_ASSERT(piece1 == m_current_slot); + TORRENT_ASSERT(piece_index == slot1); + + m_storage->swap_slots(m_current_slot, slot1); + + TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned + || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); + } + else + { + TORRENT_ASSERT(slot1 != slot2); + TORRENT_ASSERT(piece1 != piece2); + + // movement diagram: + // +-----------------------------------------+ + // | | + // +--> slot1 --> slot2 --> m_current_slot --+ + + m_slot_to_piece[slot1] = piece_index; + m_slot_to_piece[slot2] = piece1; + m_slot_to_piece[m_current_slot] = piece2; + + m_piece_to_slot[piece_index] = slot1; + m_piece_to_slot[m_current_slot] = piece2; + + if (piece1 == unassigned) + { + std::vector::iterator i = + std::find(m_free_slots.begin(), m_free_slots.end(), slot1); + TORRENT_ASSERT(i != m_free_slots.end()); + if (m_storage_mode == storage_mode_compact) + { + m_free_slots.erase(i); + m_free_slots.push_back(slot2); + } + } + + bool ret = false; + if (piece1 >= 0) + { + m_piece_to_slot[piece1] = slot2; + ret |= m_storage->swap_slots3(m_current_slot, slot1, slot2); + } + else + { + ret |= m_storage->move_slot(m_current_slot, slot1); + ret |= m_storage->move_slot(slot2, m_current_slot); + } + + if (ret) return true; + + TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned + || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); + } + } + else + { + TORRENT_ASSERT(m_piece_to_slot[m_current_slot] == has_no_slot || piece_index != m_current_slot); + TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unallocated); + TORRENT_ASSERT(piece_index == unassigned || m_piece_to_slot[piece_index] == has_no_slot); + + // the slot was identified as piece 'piece_index' + if (piece_index != unassigned) + m_piece_to_slot[piece_index] = m_current_slot; + else if (m_storage_mode == storage_mode_compact) + m_free_slots.push_back(m_current_slot); + + m_slot_to_piece[m_current_slot] = piece_index; + + TORRENT_ASSERT(m_slot_to_piece[m_current_slot] == unassigned + || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); + } + return false; } void piece_manager::switch_to_full_mode() @@ -2089,7 +2434,7 @@ namespace libtorrent if (m_storage_mode != storage_mode_compact) return piece_index; -// INVARIANT_CHECK; + INVARIANT_CHECK; TORRENT_ASSERT(piece_index >= 0); TORRENT_ASSERT(piece_index < (int)m_piece_to_slot.size()); @@ -2124,7 +2469,7 @@ namespace libtorrent // special case to make sure we don't use the last slot // when we shouldn't, since it's smaller than ordinary slots - if (*iter == m_info->num_pieces() - 1 && piece_index != *iter) + if (*iter == m_files.num_pieces() - 1 && piece_index != *iter) { if (m_free_slots.size() == 1) allocate_slots(1); @@ -2191,10 +2536,8 @@ namespace libtorrent TORRENT_ASSERT(slot_index >= 0); TORRENT_ASSERT(slot_index < (int)m_slot_to_piece.size()); - if (m_unallocated_slots.empty()) - { + if (m_free_slots.empty() && m_unallocated_slots.empty()) switch_to_full_mode(); - } return slot_index; } @@ -2204,7 +2547,7 @@ namespace libtorrent boost::recursive_mutex::scoped_lock lock(m_mutex); TORRENT_ASSERT(num_slots > 0); -// INVARIANT_CHECK; + INVARIANT_CHECK; TORRENT_ASSERT(!m_unallocated_slots.empty()); TORRENT_ASSERT(m_storage_mode == storage_mode_compact); @@ -2259,10 +2602,14 @@ namespace libtorrent { boost::recursive_mutex::scoped_lock lock(m_mutex); - if (m_unallocated_slots.empty() && m_state == state_finished) + TORRENT_ASSERT(m_current_slot <= m_files.num_pieces()); + + if (m_unallocated_slots.empty() + && m_free_slots.empty() + && m_state == state_finished) { TORRENT_ASSERT(m_storage_mode != storage_mode_compact - || m_info->num_pieces() == 0); + || m_files.num_pieces() == 0); } if (m_storage_mode != storage_mode_compact) @@ -2282,8 +2629,8 @@ namespace libtorrent { if (m_piece_to_slot.empty()) return; - TORRENT_ASSERT((int)m_piece_to_slot.size() == m_info->num_pieces()); - TORRENT_ASSERT((int)m_slot_to_piece.size() == m_info->num_pieces()); + TORRENT_ASSERT((int)m_piece_to_slot.size() == m_files.num_pieces()); + TORRENT_ASSERT((int)m_slot_to_piece.size() == m_files.num_pieces()); for (std::vector::const_iterator i = m_free_slots.begin(); i != m_free_slots.end(); ++i) @@ -2305,7 +2652,7 @@ namespace libtorrent == m_unallocated_slots.end()); } - for (int i = 0; i < m_info->num_pieces(); ++i) + for (int i = 0; i < m_files.num_pieces(); ++i) { // Check domain of piece_to_slot's elements if (m_piece_to_slot[i] != has_no_slot) @@ -2394,7 +2741,7 @@ namespace libtorrent s << "index\tslot\tpiece\n"; - for (int i = 0; i < m_info->num_pieces(); ++i) + for (int i = 0; i < m_files.num_pieces(); ++i) { s << i << "\t" << m_slot_to_piece[i] << "\t"; s << m_piece_to_slot[i] << "\n"; diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index a28916c60..afd792984 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -59,6 +59,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/session.hpp" #include "libtorrent/torrent_info.hpp" #include "libtorrent/tracker_manager.hpp" +#include "libtorrent/parse_url.hpp" #include "libtorrent/bencode.hpp" #include "libtorrent/hasher.hpp" #include "libtorrent/entry.hpp" @@ -95,20 +96,6 @@ namespace , tracker_failed_max = 5 }; - int calculate_block_size(const torrent_info& i, int default_block_size) - { - if (default_block_size < 1024) default_block_size = 1024; - - // if pieces are too small, adjust the block size - if (i.piece_length() < default_block_size) - { - return i.piece_length(); - } - - // otherwise, go with the default - return default_block_size; - } - struct find_peer_by_ip { find_peer_by_ip(tcp::endpoint const& a, const torrent* t) @@ -150,68 +137,77 @@ namespace libtorrent torrent::torrent( session_impl& ses - , aux::checker_impl& checker , boost::intrusive_ptr tf , fs::path const& save_path , tcp::endpoint const& net_interface , storage_mode_t storage_mode , int block_size , storage_constructor_type sc - , bool paused) - : m_torrent_file(tf) - , m_abort(false) - , m_paused(paused) - , m_just_paused(false) + , bool paused + , std::vector* resume_data + , int seq + , bool auto_managed) + : m_policy(this) + , m_active_time(seconds(0)) + , m_seeding_time(seconds(0)) + , m_total_uploaded(0) + , m_total_downloaded(0) + , m_started(time_now()) + , m_last_scrape(min_time()) + , m_torrent_file(tf) , m_event(tracker_request::started) - , m_block_size(0) , m_storage(0) , m_next_request(time_now()) - , m_duration(1800) - , m_complete(-1) - , m_incomplete(-1) , m_host_resolver(ses.m_io_service) -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - , m_resolving_country(false) - , m_resolve_countries(false) -#endif , m_announce_timer(ses.m_io_service) #ifndef TORRENT_DISABLE_DHT , m_last_dht_announce(time_now() - minutes(15)) #endif , m_ses(ses) - , m_checker(checker) - , m_picker(0) + , m_picker(new piece_picker()) , m_trackers(m_torrent_file->trackers()) - , m_last_working_tracker(-1) - , m_currently_trying_tracker(0) - , m_failed_trackers(0) - , m_time_scaler(0) - , m_num_pieces(0) - , m_sequenced_download_threshold(0) - , m_got_tracker_response(false) - , m_ratio(0.f) , m_total_failed_bytes(0) , m_total_redundant_bytes(0) , m_net_interface(net_interface.address(), 0) , m_save_path(complete(save_path)) , m_storage_mode(storage_mode) - , m_default_block_size(block_size) - , m_connections_initialized(true) + , m_state(torrent_status::queued_for_checking) , m_settings(ses.settings()) , m_storage_constructor(sc) + , m_progress(0.f) + , m_ratio(0.f) , m_max_uploads((std::numeric_limits::max)()) , m_num_uploads(0) , m_max_connections((std::numeric_limits::max)()) - , m_policy(this) - { -#ifndef NDEBUG - m_files_checked = false; + , m_block_size((std::min)(block_size, tf->piece_length())) + , m_complete(-1) + , m_incomplete(-1) + , m_deficit_counter(0) + , m_duration(1800) + , m_sequence_number(seq) + , m_last_working_tracker(-1) + , m_currently_trying_tracker(0) + , m_failed_trackers(0) + , m_time_scaler(0) + , m_abort(false) + , m_paused(paused) + , m_just_paused(false) + , m_auto_managed(auto_managed) +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + , m_resolving_country(false) + , m_resolve_countries(false) #endif + , m_sequential_download(false) + , m_got_tracker_response(false) + , m_connections_initialized(true) + , m_has_incoming(false) + , m_files_checked(false) + { + parse_resume_data(resume_data); } torrent::torrent( session_impl& ses - , aux::checker_impl& checker , char const* tracker_url , sha1_hash const& info_hash , char const* name @@ -220,52 +216,65 @@ namespace libtorrent , storage_mode_t storage_mode , int block_size , storage_constructor_type sc - , bool paused) - : m_torrent_file(new torrent_info(info_hash)) - , m_abort(false) - , m_paused(paused) - , m_just_paused(false) + , bool paused + , std::vector* resume_data + , int seq + , bool auto_managed) + : m_policy(this) + , m_active_time(seconds(0)) + , m_seeding_time(seconds(0)) + , m_total_uploaded(0) + , m_total_downloaded(0) + , m_started(time_now()) + , m_last_scrape(min_time()) + , m_torrent_file(new torrent_info(info_hash)) , m_event(tracker_request::started) - , m_block_size(0) , m_storage(0) , m_next_request(time_now()) - , m_duration(1800) - , m_complete(-1) - , m_incomplete(-1) , m_host_resolver(ses.m_io_service) -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - , m_resolving_country(false) - , m_resolve_countries(false) -#endif , m_announce_timer(ses.m_io_service) #ifndef TORRENT_DISABLE_DHT , m_last_dht_announce(time_now() - minutes(15)) #endif , m_ses(ses) - , m_checker(checker) - , m_picker(0) - , m_last_working_tracker(-1) - , m_currently_trying_tracker(0) - , m_failed_trackers(0) - , m_time_scaler(0) - , m_num_pieces(0) - , m_sequenced_download_threshold(0) - , m_got_tracker_response(false) - , m_ratio(0.f) + , m_picker(new piece_picker()) , m_total_failed_bytes(0) , m_total_redundant_bytes(0) , m_net_interface(net_interface.address(), 0) , m_save_path(complete(save_path)) , m_storage_mode(storage_mode) - , m_default_block_size(block_size) - , m_connections_initialized(false) + , m_state(torrent_status::queued_for_checking) , m_settings(ses.settings()) , m_storage_constructor(sc) + , m_progress(0.f) + , m_ratio(0.f) , m_max_uploads((std::numeric_limits::max)()) , m_num_uploads(0) , m_max_connections((std::numeric_limits::max)()) - , m_policy(this) + , m_block_size(block_size) + , m_complete(-1) + , m_incomplete(-1) + , m_deficit_counter(0) + , m_duration(1800) + , m_sequence_number(seq) + , m_last_working_tracker(-1) + , m_currently_trying_tracker(0) + , m_failed_trackers(0) + , m_time_scaler(0) + , m_abort(false) + , m_paused(paused) + , m_just_paused(false) + , m_auto_managed(auto_managed) +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + , m_resolving_country(false) + , m_resolve_countries(false) +#endif + , m_sequential_download(false) + , m_got_tracker_response(false) + , m_connections_initialized(false) + , m_has_incoming(false) { + parse_resume_data(resume_data); #ifndef NDEBUG m_files_checked = false; #endif @@ -280,14 +289,34 @@ namespace libtorrent } } + void torrent::parse_resume_data(std::vector* resume_data) + { + if (!resume_data) return; + m_resume_data.swap(*resume_data); + if (lazy_bdecode(&m_resume_data[0], &m_resume_data[0] + + m_resume_data.size(), m_resume_entry) != 0) + { + std::vector().swap(m_resume_data); + if (m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), "parse failed")); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_ses.m_logger) << "fastresume data for " + << torrent_file().name() << " rejected: parse failed\n"; +#endif + } + } + } + void torrent::start() { boost::weak_ptr self(shared_from_this()); if (m_torrent_file->is_valid()) init(); if (m_abort) return; - m_announce_timer.expires_from_now(seconds(1)); - m_announce_timer.async_wait(m_ses.m_strand.wrap( - bind(&torrent::on_announce_disp, self, _1))); + error_code ec; + m_announce_timer.expires_from_now(seconds(1), ec); + m_announce_timer.async_wait( + bind(&torrent::on_announce_disp, self, _1)); } #ifndef TORRENT_DISABLE_DHT @@ -296,10 +325,10 @@ namespace libtorrent if (m_ses.m_listen_sockets.empty()) return false; if (!m_ses.m_dht) return false; + if (!m_files_checked) return false; // don't announce private torrents if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false; - if (m_trackers.empty()) return true; return m_failed_trackers > 0 || !m_ses.settings().use_dht_as_fallback; @@ -321,7 +350,7 @@ namespace libtorrent INVARIANT_CHECK; -#if defined(TORRENT_VERBOSE_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) { @@ -395,20 +424,321 @@ namespace libtorrent TORRENT_ASSERT(m_torrent_file->num_files() > 0); TORRENT_ASSERT(m_torrent_file->total_size() >= 0); - m_have_pieces.resize(m_torrent_file->num_pieces(), false); + m_block_size = (std::min)(m_block_size, m_torrent_file->piece_length()); + + if (m_torrent_file->num_pieces() + > piece_picker::max_pieces) + { + m_error = "too many pieces in torrent"; + pause(); + } + // the shared_from_this() will create an intentional // cycle of ownership, se the hpp file for description. m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file - , m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor); + , m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor + , m_storage_mode); m_storage = m_owning_storage.get(); - m_block_size = calculate_block_size(*m_torrent_file, m_default_block_size); - m_picker.reset(new piece_picker( - m_torrent_file->piece_length() / m_block_size - , int((m_torrent_file->total_size()+m_block_size-1)/m_block_size))); + m_picker->init((std::max)(m_torrent_file->piece_length() / m_block_size, 1) + , int((m_torrent_file->total_size()+m_block_size-1)/m_block_size)); std::vector const& url_seeds = m_torrent_file->url_seeds(); std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds , m_web_seeds.begin())); + + set_state(torrent_status::queued_for_checking); + + if (m_resume_entry.type() == lazy_entry::dict_t) + { + char const* error = 0; + if (m_resume_entry.dict_find_string_value("file-format") != "libtorrent resume file") + error = "invalid file format tag"; + + std::string info_hash = m_resume_entry.dict_find_string_value("info-hash"); + if (!error && info_hash.empty()) + error = "missing info-hash"; + + if (!error && sha1_hash(info_hash) != m_torrent_file->info_hash()) + error = "mismatching info-hash"; + + if (error && m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), error)); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_ses.m_logger) << "fastresume data for " + << torrent_file().name() << " rejected: " + << error << "\n"; +#endif + } + + if (error) + { + std::vector().swap(m_resume_data); + lazy_entry().swap(m_resume_entry); + } + else + { + read_resume_data(m_resume_entry); + } + } + + m_storage->async_check_fastresume(&m_resume_entry + , bind(&torrent::on_resume_data_checked + , shared_from_this(), _1, _2)); + } + + void torrent::on_resume_data_checked(int ret, disk_io_job const& j) + { + session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); + + if (ret == piece_manager::fatal_disk_error) + { + if (m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str)); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_ses.m_logger) << time_now_string() << ": fatal disk error [" + " error: " << j.str << + " torrent: " << torrent_file().name() << + " ]\n"; +#endif + } + m_error = j.str; + pause(); + + std::vector().swap(m_resume_data); + lazy_entry().swap(m_resume_entry); + + return; + } + + if (m_resume_entry.type() == lazy_entry::dict_t) + { + // parse out "peers" from the resume data and add them to the peer list + if (lazy_entry const* peers_entry = m_resume_entry.dict_find_list("peers")) + { + peer_id id(0); + + for (int i = 0; i < peers_entry->list_size(); ++i) + { + lazy_entry const* e = peers_entry->list_at(i); + if (e->type() != lazy_entry::dict_t) continue; + std::string ip = e->dict_find_string_value("ip"); + int port = e->dict_find_int_value("port"); + if (ip.empty() || port == 0) continue; + tcp::endpoint a(address::from_string(ip), (unsigned short)port); + m_policy.peer_from_tracker(a, id, peer_info::resume_data, 0); + } + } + + // parse out "banned_peers" and add them as banned + if (lazy_entry const* banned_peers_entry = m_resume_entry.dict_find_list("banned_peers")) + { + peer_id id(0); + + for (int i = 0; i < banned_peers_entry->list_size(); ++i) + { + lazy_entry const* e = banned_peers_entry->list_at(i); + if (e->type() != lazy_entry::dict_t) continue; + std::string ip = e->dict_find_string_value("ip"); + int port = e->dict_find_int_value("port"); + if (ip.empty() || port == 0) continue; + tcp::endpoint a(address::from_string(ip), (unsigned short)port); + policy::peer* p = m_policy.peer_from_tracker(a, id, peer_info::resume_data, 0); + if (p) p->banned = true; + } + } + } + + bool fastresume_rejected = !j.str.empty(); + + if (fastresume_rejected && m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), j.str)); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_ses.m_logger) << "fastresume data for " + << torrent_file().name() << " rejected: " + << j.str << "\n"; +#endif + } + + if (ret == 0) + { + // there are either no files for this torrent + // or the resume_data was accepted + + if (!fastresume_rejected && m_resume_entry.type() == lazy_entry::dict_t) + { + // parse have bitmask + lazy_entry const* pieces = m_resume_entry.dict_find("pieces"); + if (pieces && pieces->type() == lazy_entry::string_t + && int(pieces->string_length()) == m_torrent_file->num_pieces()) + { + char const* pieces_str = pieces->string_ptr(); + for (int i = 0, end(pieces->string_length()); i < end; ++i) + { + if ((pieces_str[i] & 1) == 0) continue; + m_picker->we_have(i); + } + } + + // parse unfinished pieces + int num_blocks_per_piece = + static_cast(torrent_file().piece_length()) / block_size(); + + if (lazy_entry const* unfinished_ent = m_resume_entry.dict_find_list("unfinished")) + { + for (int i = 0; i < unfinished_ent->list_size(); ++i) + { + lazy_entry const* e = unfinished_ent->list_at(i); + if (e->type() != lazy_entry::dict_t) continue; + int piece = e->dict_find_int_value("piece", -1); + if (piece < 0 || piece > torrent_file().num_pieces()) continue; + + if (m_picker->have_piece(piece)) + m_picker->we_dont_have(piece); + + std::string bitmask = e->dict_find_string_value("bitmask"); + if (bitmask.empty()) continue; + + const int num_bitmask_bytes = (std::max)(num_blocks_per_piece / 8, 1); + if ((int)bitmask.size() != num_bitmask_bytes) continue; + for (int j = 0; j < num_bitmask_bytes; ++j) + { + unsigned char bits = bitmask[j]; + int num_bits = (std::min)(num_blocks_per_piece - j*8, 8); + for (int k = 0; k < num_bits; ++k) + { + const int bit = j * 8 + k; + if (bits & (1 << k)) + { + m_picker->mark_as_finished(piece_block(piece, bit), 0); + if (m_picker->is_piece_finished(piece)) + async_verify_piece(piece, bind(&torrent::piece_finished + , shared_from_this(), piece, _1)); + } + } + } + } + } + } + + files_checked(); + } + else + { + // either the fastresume data was rejected or there are + // some files + m_ses.check_torrent(shared_from_this()); + } + + std::vector().swap(m_resume_data); + lazy_entry().swap(m_resume_entry); + } + + void torrent::force_recheck() + { + if (m_state == torrent_status::checking_files + || m_state == torrent_status::queued_for_checking) + return; + + disconnect_all(); + + m_owning_storage->async_release_files(); + m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file + , m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor + , m_storage_mode); + m_storage = m_owning_storage.get(); + m_picker.reset(new piece_picker); + m_picker->init(m_torrent_file->piece_length() / m_block_size + , int((m_torrent_file->total_size()+m_block_size-1)/m_block_size)); + // assume that we don't have anything + m_files_checked = false; + set_state(torrent_status::queued_for_checking); + + if (m_auto_managed) + set_queue_position((std::numeric_limits::max)()); + + std::vector().swap(m_resume_data); + lazy_entry().swap(m_resume_entry); + m_storage->async_check_fastresume(&m_resume_entry + , bind(&torrent::on_force_recheck + , shared_from_this(), _1, _2)); + } + + void torrent::on_force_recheck(int ret, disk_io_job const& j) + { + session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); + + if (ret == piece_manager::fatal_disk_error) + { + if (m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str)); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_ses.m_logger) << time_now_string() << ": fatal disk error [" + " error: " << j.str << + " torrent: " << torrent_file().name() << + " ]\n"; +#endif + } + m_error = j.str; + pause(); + return; + } + m_ses.check_torrent(shared_from_this()); + } + + void torrent::start_checking() + { + set_state(torrent_status::checking_files); + + m_storage->async_check_files(bind( + &torrent::on_piece_checked + , shared_from_this(), _1, _2)); + } + + void torrent::on_piece_checked(int ret, disk_io_job const& j) + { + session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); + + if (ret == piece_manager::disk_check_aborted) + { + m_error = "aborted"; + m_ses.done_checking(shared_from_this()); + return; + } + if (ret == piece_manager::fatal_disk_error) + { + if (m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str)); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_ses.m_logger) << time_now_string() << ": fatal disk error [" + " error: " << j.str << + " torrent: " << torrent_file().name() << + " ]\n"; +#endif + } + m_error = j.str; + pause(); + m_ses.done_checking(shared_from_this()); + return; + } + + m_progress = j.piece / float(torrent_file().num_pieces()); + + TORRENT_ASSERT(m_picker); + if (j.offset >= 0 && !m_picker->have_piece(j.offset)) + m_picker->we_have(j.offset); + + // we're not done checking yet + // this handler will be called repeatedly until + // we're done, or encounter a failure + if (ret == piece_manager::need_full_check) return; + + m_ses.done_checking(shared_from_this()); + files_checked(); } void torrent::use_interface(const char* net_interface) @@ -419,7 +749,7 @@ namespace libtorrent } void torrent::on_announce_disp(boost::weak_ptr p - , asio::error_code const& e) + , error_code const& e) { if (e) return; boost::shared_ptr t = p.lock(); @@ -428,34 +758,31 @@ namespace libtorrent } void torrent::on_announce() -#ifndef NDEBUG - try -#endif { if (m_abort) return; boost::weak_ptr self(shared_from_this()); + error_code ec; if (!m_torrent_file->priv()) { // announce on local network every 5 minutes - m_announce_timer.expires_from_now(minutes(5)); - m_announce_timer.async_wait(m_ses.m_strand.wrap( - bind(&torrent::on_announce_disp, self, _1))); + m_announce_timer.expires_from_now(minutes(5), ec); + m_announce_timer.async_wait( + bind(&torrent::on_announce_disp, self, _1)); // announce with the local discovery service - if (!m_paused) - m_ses.announce_lsd(m_torrent_file->info_hash()); + if (!is_paused()) m_ses.announce_lsd(m_torrent_file->info_hash()); } else { - m_announce_timer.expires_from_now(minutes(15)); - m_announce_timer.async_wait(m_ses.m_strand.wrap( - bind(&torrent::on_announce_disp, self, _1))); + m_announce_timer.expires_from_now(minutes(15), ec); + m_announce_timer.async_wait( + bind(&torrent::on_announce_disp, self, _1)); } #ifndef TORRENT_DISABLE_DHT - if (m_paused) return; + if (is_paused()) return; if (!m_ses.m_dht) return; ptime now = time_now(); if (should_announce_dht() && now - m_last_dht_announce > minutes(14)) @@ -463,17 +790,10 @@ namespace libtorrent m_last_dht_announce = now; m_ses.m_dht->announce(m_torrent_file->info_hash() , m_ses.m_listen_sockets.front().external_port - , m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1))); + , bind(&torrent::on_dht_announce_response_disp, self, _1)); } #endif } -#ifndef NDEBUG - catch (std::exception& e) - { - std::cerr << e.what() << std::endl; - TORRENT_ASSERT(false); - }; -#endif #ifndef TORRENT_DISABLE_DHT @@ -489,10 +809,10 @@ namespace libtorrent { if (peers.empty()) return; - if (m_ses.m_alerts.should_post(alert::info)) + if (m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(tracker_reply_alert( - get_handle(), peers.size(), "Got peers from DHT")); + m_ses.m_alerts.post_alert(dht_reply_alert( + get_handle(), peers.size())); } std::for_each(peers.begin(), peers.end(), bind( &policy::peer_from_tracker, boost::ref(m_policy), _1, peer_id(0) @@ -512,36 +832,37 @@ namespace libtorrent req.info_hash = m_torrent_file->info_hash(); req.kind = tracker_request::scrape_request; req.url = m_trackers[m_currently_trying_tracker].url; - m_ses.m_tracker_manager.queue_request(m_ses.m_strand, m_ses.m_half_open, req + m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req , tracker_login(), m_ses.m_listen_interface.address(), shared_from_this()); + + m_last_scrape = time_now(); } // returns true if it is time for this torrent to make another // tracker request bool torrent::should_request() { - INVARIANT_CHECK; +// INVARIANT_CHECK; if (m_trackers.empty()) return false; + if (!m_files_checked) return false; if (m_just_paused) { m_just_paused = false; return true; } - return !m_paused && m_next_request < time_now(); + return !is_paused() && m_next_request < time_now(); } - void torrent::tracker_warning(std::string const& msg) + void torrent::tracker_warning(tracker_request const& req, std::string const& msg) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); INVARIANT_CHECK; - if (m_ses.m_alerts.should_post(alert::warning)) - { - m_ses.m_alerts.post_alert(tracker_warning_alert(get_handle(), msg)); - } + if (m_ses.m_alerts.should_post()) + m_ses.m_alerts.post_alert(tracker_warning_alert(get_handle(), req.url, msg)); } void torrent::tracker_scrape_response(tracker_request const& req @@ -555,12 +876,10 @@ namespace libtorrent if (complete >= 0) m_complete = complete; if (incomplete >= 0) m_incomplete = incomplete; - if (m_ses.m_alerts.should_post(alert::info)) + if (m_ses.m_alerts.should_post()) { - std::stringstream s; - s << "Got scrape response from tracker: " << req.url; m_ses.m_alerts.post_alert(scrape_reply_alert( - get_handle(), m_incomplete, m_complete, s.str())); + get_handle(), m_incomplete, m_complete, req.url)); } } @@ -569,13 +888,17 @@ namespace libtorrent , std::vector& peer_list , int interval , int complete - , int incomplete) + , int incomplete + , address const& external_ip) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); INVARIANT_CHECK; TORRENT_ASSERT(r.kind == tracker_request::announce_request); + if (external_ip != address()) + m_ses.set_external_address(external_ip); + m_failed_trackers = 0; // announce intervals less than 5 minutes // are insane. @@ -590,11 +913,13 @@ namespace libtorrent if (complete >= 0) m_complete = complete; if (incomplete >= 0) m_incomplete = incomplete; + if (complete >= 0 && incomplete >= 0) + m_last_scrape = time_now(); // connect to random peers from the list std::random_shuffle(peer_list.begin(), peer_list.end()); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING std::stringstream s; s << "TRACKER RESPONSE:\n" "interval: " << m_duration << "\n" @@ -607,6 +932,7 @@ namespace libtorrent if (!i->pid.is_all_zeros()) s << " " << i->pid << " " << identify_client(i->pid); s << "\n"; } + s << "external ip: " << external_ip << "\n"; debug_log(s.str()); #endif // for each of the peers we got from the tracker @@ -617,49 +943,45 @@ namespace libtorrent if (i->pid == m_ses.get_peer_id()) continue; - try - { - tcp::endpoint a(address::from_string(i->ip), i->port); + error_code ec; + tcp::endpoint a(address::from_string(i->ip, ec), i->port); - if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - debug_log("blocked ip from tracker: " + i->ip); -#endif - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(peer_blocked_alert(a.address() - , "peer from tracker blocked by IP filter")); - } - - continue; - } - - m_policy.peer_from_tracker(a, i->pid, peer_info::tracker, 0); - } - catch (std::exception&) + if (ec) { // assume this is because we got a hostname instead of // an ip address from the tracker tcp::resolver::query q(i->ip, boost::lexical_cast(i->port)); - m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( - bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid))); - } + m_host_resolver.async_resolve(q, + bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid)); + } + else + { + if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) + { +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + debug_log("blocked ip from tracker: " + i->ip); +#endif + if (m_ses.m_alerts.should_post()) + m_ses.m_alerts.post_alert(peer_blocked_alert(a.address())); + + continue; + } + + m_policy.peer_from_tracker(a, i->pid, peer_info::tracker, 0); + } } - if (m_ses.m_alerts.should_post(alert::info)) + if (m_ses.m_alerts.should_post()) { - std::stringstream s; - s << "Got response from tracker: " << r.url; m_ses.m_alerts.post_alert(tracker_reply_alert( - get_handle(), peer_list.size(), s.str())); + get_handle(), peer_list.size(), r.url)); } m_got_tracker_response = true; } - void torrent::on_peer_name_lookup(asio::error_code const& e, tcp::resolver::iterator host - , peer_id pid) try + void torrent::on_peer_name_lookup(error_code const& e, tcp::resolver::iterator host + , peer_id pid) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); @@ -670,13 +992,12 @@ namespace libtorrent if (m_ses.m_ip_filter.access(host->endpoint().address()) & ip_filter::blocked) { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING debug_log("blocked ip from tracker: " + host->endpoint().address().to_string()); #endif - if (m_ses.m_alerts.should_post(alert::info)) + if (m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(peer_blocked_alert(host->endpoint().address() - , "peer from tracker blocked by IP filter")); + m_ses.m_alerts.post_alert(peer_blocked_alert(host->endpoint().address())); } return; @@ -684,8 +1005,6 @@ namespace libtorrent m_policy.peer_from_tracker(*host, pid, peer_info::tracker, 0); } - catch (std::exception&) - {}; size_type torrent::bytes_left() const { @@ -710,12 +1029,12 @@ namespace libtorrent const int last_piece = m_torrent_file->num_pieces() - 1; size_type total_done - = size_type(m_num_pieces) * m_torrent_file->piece_length(); + = size_type(num_have()) * m_torrent_file->piece_length(); // if we have the last piece, we have to correct // the amount we have, since the first calculation // assumed all pieces were of equal size - if (m_have_pieces[last_piece]) + if (m_picker->have_piece(last_piece)) { int corr = m_torrent_file->piece_size(last_piece) - m_torrent_file->piece_length(); @@ -741,19 +1060,19 @@ namespace libtorrent return make_tuple(m_torrent_file->total_size() , m_torrent_file->total_size()); - TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered()); - size_type wanted_done = size_type(m_num_pieces - m_picker->num_have_filtered()) + TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered()); + size_type wanted_done = size_type(num_have() - m_picker->num_have_filtered()) * piece_size; TORRENT_ASSERT(wanted_done >= 0); size_type total_done - = size_type(m_num_pieces) * piece_size; - TORRENT_ASSERT(m_num_pieces < m_torrent_file->num_pieces()); + = size_type(num_have()) * piece_size; + TORRENT_ASSERT(num_have() < m_torrent_file->num_pieces()); // if we have the last piece, we have to correct // the amount we have, since the first calculation // assumed all pieces were of equal size - if (m_have_pieces[last_piece]) + if (m_picker->have_piece(last_piece)) { TORRENT_ASSERT(total_done >= piece_size); int corr = m_torrent_file->piece_size(last_piece) @@ -782,7 +1101,7 @@ namespace libtorrent { int corr = 0; int index = i->index; - if (m_have_pieces[index]) continue; + if (m_picker->have_piece(index)) continue; TORRENT_ASSERT(i->finished <= m_picker->blocks_in_piece(index)); #ifndef NDEBUG @@ -827,7 +1146,7 @@ namespace libtorrent = pc->downloading_piece_progress(); if (p) { - if (m_have_pieces[p->piece_index]) + if (m_picker->have_piece(p->piece_index)) continue; piece_block block(p->piece_index, p->block_index); @@ -864,16 +1183,16 @@ namespace libtorrent wanted_done += i->second; } + TORRENT_ASSERT(total_done <= m_torrent_file->total_size()); + TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size()); + #ifndef NDEBUG if (total_done >= m_torrent_file->total_size()) { // Thist happens when a piece has been downloaded completely // but not yet verified against the hash - std::copy(m_have_pieces.begin(), m_have_pieces.end() - , std::ostream_iterator(std::cerr, " ")); - std::cerr << std::endl; - std::cerr << "num_pieces: " << m_num_pieces << std::endl; + std::cerr << "num_have: " << num_have() << std::endl; std::cerr << "unfinished:" << std::endl; @@ -908,92 +1227,121 @@ namespace libtorrent return make_tuple(total_done, wanted_done); } - void torrent::piece_finished(int index, bool passed_hash_check) + // passed_hash_check + // 0: success, piece passed check + // -1: disk failure + // -2: piece failed check + void torrent::piece_finished(int index, int passed_hash_check) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_ses.m_logger) << time_now_string() << " *** PIECE_FINISHED [ p: " - << index << " chk: " << (passed_hash_check?"passed":"failed") << " ]\n"; + << index << " chk: " << ((passed_hash_check == 0) + ?"passed":passed_hash_check == -1 + ?"disk failed":"failed") << " ]\n"; #endif - bool was_seed = is_seed(); - bool was_finished = m_picker->num_filtered() + num_pieces() - == torrent_file().num_pieces(); + TORRENT_ASSERT(valid_metadata()); - if (passed_hash_check) + if (passed_hash_check == 0) { - if (m_ses.m_alerts.should_post(alert::debug)) - { - m_ses.m_alerts.post_alert(piece_finished_alert(get_handle() - , index, "piece finished")); - } // the following call may cause picker to become invalid // in case we just became a seed - announce_piece(index); - TORRENT_ASSERT(valid_metadata()); - // if we just became a seed, picker is now invalid, since it - // is deallocated by the torrent once it starts seeding - if (!was_finished - && (is_seed() - || m_picker->num_filtered() + num_pieces() - == torrent_file().num_pieces())) - { - // torrent finished - // i.e. all the pieces we're interested in have - // been downloaded. Release the files (they will open - // in read only mode if needed) - try { finished(); } - catch (std::exception& e) - { -#ifndef NDEBUG - std::cerr << e.what() << std::endl; - TORRENT_ASSERT(false); -#endif - } - } + piece_passed(index); + } + else if (passed_hash_check == -2) + { + // piece_failed() will restore the piece + piece_failed(index); } else { - piece_failed(index); + TORRENT_ASSERT(passed_hash_check == -1); + m_picker->restore_piece(index); + restore_piece_state(index); + } + } + + void torrent::piece_passed(int index) + { +// INVARIANT_CHECK; + + TORRENT_ASSERT(index >= 0); + TORRENT_ASSERT(index < m_torrent_file->num_pieces()); + + if (m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(piece_finished_alert(get_handle() + , index)); } -#ifndef NDEBUG - try + bool was_finished = m_picker->num_filtered() + num_have() + == torrent_file().num_pieces(); + + std::vector downloaders; + m_picker->get_downloaders(downloaders, index); + + // increase the trust point of all peers that sent + // parts of this piece. + std::set peers; + std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin())); + + m_picker->we_have(index); + for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) + (*i)->announce_piece(index); + + for (std::set::iterator i = peers.begin() + , end(peers.end()); i != end; ++i) { + policy::peer* p = static_cast(*i); + if (p == 0) continue; + p->on_parole = false; + ++p->trust_points; + // TODO: make this limit user settable + if (p->trust_points > 20) p->trust_points = 20; + if (p->connection) p->connection->received_valid_data(index); + } + +#ifndef TORRENT_DISABLE_EXTENSIONS + for (extension_list_t::iterator i = m_extensions.begin() + , end(m_extensions.end()); i != end; ++i) + { +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + (*i)->on_piece_pass(index); +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception&) {} #endif - - m_policy.piece_finished(index, passed_hash_check); - -#ifndef NDEBUG - } - catch (std::exception const& e) - { - std::cerr << e.what() << std::endl; - TORRENT_ASSERT(false); } #endif -#ifndef NDEBUG - try + // since this piece just passed, we might have + // become uninterested in some peers where this + // was the last piece we were interested in + for (peer_iterator i = m_connections.begin() + , end(m_connections.end()); i != end; ++i) { -#endif - - if (!was_seed && is_seed()) - { - TORRENT_ASSERT(passed_hash_check); - completed(); + peer_connection* p = *i; + // if we're not interested already, no need to check + if (!p->is_interesting()) continue; + // if the peer doesn't have the piece we just got, it + // wouldn't affect our interest + if (!p->has_piece(index)) continue; + p->update_interest(); } -#ifndef NDEBUG - } - catch (std::exception const& e) + if (!was_finished && is_finished()) { - std::cerr << e.what() << std::endl; - TORRENT_ASSERT(false); + // torrent finished + // i.e. all the pieces we're interested in have + // been downloaded. Release the files (they will open + // in read only mode if needed) + finished(); + // if we just became a seed, picker is now invalid, since it + // is deallocated by the torrent once it starts seeding } -#endif - } void torrent::piece_failed(int index) @@ -1011,12 +1359,9 @@ namespace libtorrent TORRENT_ASSERT(index >= 0); TORRENT_ASSERT(index < m_torrent_file->num_pieces()); - if (m_ses.m_alerts.should_post(alert::info)) - { - std::stringstream s; - s << "hash for piece " << index << " failed"; - m_ses.m_alerts.post_alert(hash_failed_alert(get_handle(), index, s.str())); - } + if (m_ses.m_alerts.should_post()) + m_ses.m_alerts.post_alert(hash_failed_alert(get_handle(), index)); + // increase the total amount of failed bytes m_total_failed_bytes += m_torrent_file->piece_size(index); @@ -1029,11 +1374,29 @@ namespace libtorrent std::set peers; std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin())); +#ifndef NDEBUG + for (std::vector::iterator i = downloaders.begin() + , end(downloaders.end()); i != end; ++i) + { + policy::peer* p = (policy::peer*)*i; + if (p && p->connection) + { + p->connection->piece_failed = true; + } + } +#endif + #ifndef TORRENT_DISABLE_EXTENSIONS for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) { - try { (*i)->on_piece_failed(index); } catch (std::exception&) {} +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + (*i)->on_piece_failed(index); +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception&) {} +#endif } #endif @@ -1052,12 +1415,12 @@ namespace libtorrent { // we don't trust this peer anymore // ban it. - if (m_ses.m_alerts.should_post(alert::info)) + if (m_ses.m_alerts.should_post()) { + peer_id pid; + if (p->connection) pid = p->connection->pid(); m_ses.m_alerts.post_alert(peer_ban_alert( - p->ip - , get_handle() - , "banning peer because of too many corrupt pieces")); + get_handle(), p->ip, pid)); } // mark the peer as banned @@ -1065,11 +1428,15 @@ namespace libtorrent if (p->connection) { -#if defined(TORRENT_VERBOSE_LOGGING) +#ifdef TORRENT_LOGGING + (*m_ses.m_logger) << time_now_string() << " *** BANNING PEER [ " << p->ip + << " ] 'too many corrupt pieces'\n"; +#endif +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*p->connection->m_logger) << "*** BANNING PEER [ " << p->ip << " ] 'too many corrupt pieces'\n"; #endif - p->connection->disconnect(); + p->connection->disconnect("too many corrupt pieces, banning peer"); } } } @@ -1086,9 +1453,20 @@ namespace libtorrent m_picker->restore_piece(index); restore_piece_state(index); TORRENT_ASSERT(m_storage); - m_storage->mark_failed(index); - TORRENT_ASSERT(m_have_pieces[index] == false); + TORRENT_ASSERT(m_picker->have_piece(index) == false); + +#ifndef NDEBUG + for (std::vector::iterator i = downloaders.begin() + , end(downloaders.end()); i != end; ++i) + { + policy::peer* p = (policy::peer*)*i; + if (p && p->connection) + { + p->connection->piece_failed = false; + } + } +#endif } void torrent::restore_piece_state(int index) @@ -1098,13 +1476,13 @@ namespace libtorrent i != m_connections.end(); ++i) { peer_connection* p = *i; - std::deque const& dq = p->download_queue(); + std::deque const& dq = p->download_queue(); std::deque const& rq = p->request_queue(); - for (std::deque::const_iterator k = dq.begin() + for (std::deque::const_iterator k = dq.begin() , end(dq.end()); k != end; ++k) { - if (k->piece_index != index) continue; - m_picker->mark_as_downloading(*k, p->peer_info_struct() + if (k->block.piece_index != index) continue; + m_picker->mark_as_downloading(k->block, p->peer_info_struct() , (piece_picker::piece_state_t)p->peer_speed()); } for (std::deque::const_iterator k = rq.begin() @@ -1124,12 +1502,12 @@ namespace libtorrent m_abort = true; // if the torrent is paused, it doesn't need // to announce with even=stopped again. - if (!m_paused) + if (!is_paused()) m_event = tracker_request::stopped; // disconnect all peers and close all // files belonging to the torrents -#if defined(TORRENT_VERBOSE_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) { @@ -1143,7 +1521,8 @@ namespace libtorrent bind(&torrent::on_files_released, shared_from_this(), _1, _2)); m_owning_storage = 0; - m_announce_timer.cancel(); + error_code ec; + m_announce_timer.cancel(ec); m_host_resolver.cancel(); } @@ -1151,16 +1530,15 @@ namespace libtorrent { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - if (alerts().should_post(alert::warning)) + if (ret != 0) { - if (ret != 0) - { - alerts().post_alert(torrent_deleted_alert(get_handle(), "delete files failed: " + j.str)); - } - else - { - alerts().post_alert(torrent_deleted_alert(get_handle(), "files deleted")); - } + if (alerts().should_post()) + alerts().post_alert(torrent_delete_failed_alert(get_handle(), j.str)); + } + else + { + if (alerts().should_post()) + alerts().post_alert(torrent_deleted_alert(get_handle())); } } @@ -1169,74 +1547,55 @@ namespace libtorrent /* session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - if (alerts().should_post(alert::warning)) + if (alerts().should_post()) { - alerts().post_alert(torrent_paused_alert(get_handle(), "torrent paused")); + alerts().post_alert(torrent_paused_alert(get_handle())); } */ } + void torrent::on_save_resume_data(int ret, disk_io_job const& j) + { + session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); + + if (!j.resume_data && alerts().should_post()) + { + alerts().post_alert(save_resume_data_failed_alert(get_handle(), j.str)); + return; + } + + if (j.resume_data && alerts().should_post()) + { + write_resume_data(*j.resume_data); + alerts().post_alert(save_resume_data_alert(j.resume_data + , get_handle())); + } + } + + void torrent::on_file_renamed(int ret, disk_io_job const& j) + { + session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); + + { + if (ret == 0) + { + if (alerts().should_post()) + alerts().post_alert(file_renamed_alert(get_handle(), j.str, j.piece)); + } + else + { + if (alerts().should_post()) + alerts().post_alert(file_rename_failed_alert(get_handle(), j.str, j.piece)); + } + } + } + void torrent::on_torrent_paused(int ret, disk_io_job const& j) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - if (alerts().should_post(alert::warning)) - { - alerts().post_alert(torrent_paused_alert(get_handle(), "torrent paused")); - } - } - - void torrent::announce_piece(int index) - { -// INVARIANT_CHECK; - - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < m_torrent_file->num_pieces()); - - std::vector downloaders; - m_picker->get_downloaders(downloaders, index); - - // increase the trust point of all peers that sent - // parts of this piece. - std::set peers; - std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin())); - - if (!m_have_pieces[index]) - m_num_pieces++; - m_have_pieces[index] = true; - - TORRENT_ASSERT(std::accumulate(m_have_pieces.begin(), m_have_pieces.end(), 0) - == m_num_pieces); - - m_picker->we_have(index); - for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) - try { (*i)->announce_piece(index); } catch (std::exception&) {} - - for (std::set::iterator i = peers.begin() - , end(peers.end()); i != end; ++i) - { - policy::peer* p = static_cast(*i); - if (p == 0) continue; - p->on_parole = false; - ++p->trust_points; - // TODO: make this limit user settable - if (p->trust_points > 20) p->trust_points = 20; - if (p->connection) p->connection->received_valid_data(index); - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - try { (*i)->on_piece_pass(index); } catch (std::exception&) {} - } -#endif - if (is_seed()) - { - m_picker.reset(); - if (m_ses.settings().free_torrent_hashes) - m_torrent_file->seed_free(); - } + if (alerts().should_post()) + alerts().post_alert(torrent_paused_alert(get_handle())); } std::string torrent::tracker_login() const @@ -1273,6 +1632,7 @@ namespace libtorrent bool was_finished = is_finished(); bool filter_updated = m_picker->set_piece_priority(index, priority); + TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered()); if (filter_updated) update_peer_interest(was_finished); } @@ -1310,6 +1670,7 @@ namespace libtorrent TORRENT_ASSERT(*i >= 0); TORRENT_ASSERT(*i <= 7); filter_updated |= m_picker->set_piece_priority(index, *i); + TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered()); } if (filter_updated) update_peer_interest(was_finished); } @@ -1363,7 +1724,7 @@ namespace libtorrent for (int i = 0; i < int(files.size()); ++i) { size_type start = position; - size_type size = m_torrent_file->file_at(i).size; + size_type size = m_torrent_file->files().at(i).size; if (size == 0) continue; position += size; // mark all pieces of the file with this file's priority @@ -1388,10 +1749,17 @@ namespace libtorrent { for (peer_iterator i = begin(); i != end(); ++i) (*i)->update_interest(); - + + // if we used to be finished, but we aren't anymore + // we may need to connect to peers again + if (!is_finished() && was_finished) + m_policy.recalculate_connect_candidates(); + // the torrent just became finished if (is_finished() && !was_finished) finished(); + else if (!is_finished() && was_finished) + resume_download(); } void torrent::filter_piece(int index, bool filter) @@ -1487,7 +1855,7 @@ namespace libtorrent for (int i = 0; i < (int)bitmask.size(); ++i) { size_type start = position; - position += m_torrent_file->file_at(i).size; + position += m_torrent_file->files().at(i).size; // is the file selected for download? if (!bitmask[i]) { @@ -1580,7 +1948,7 @@ namespace libtorrent } } - void torrent::remove_peer(peer_connection* p) try + void torrent::remove_peer(peer_connection* p) { // INVARIANT_CHECK; @@ -1607,16 +1975,11 @@ namespace libtorrent } else { - // if we're a seed, we don't keep track of piece availability - if (!is_seed()) + if (m_picker.get()) { - const std::vector& pieces = p->get_bitfield(); - - for (std::vector::const_iterator i = pieces.begin(); - i != pieces.end(); ++i) - { - if (*i) peer_lost(static_cast(i - pieces.begin())); - } + bitfield const& pieces = p->get_bitfield(); + TORRENT_ASSERT(pieces.count() < int(pieces.size())); + m_picker->dec_refcount(pieces); } } } @@ -1641,19 +2004,12 @@ namespace libtorrent } } } - catch (std::exception& e) - { -#ifndef NDEBUG - std::string err = e.what(); -#endif - TORRENT_ASSERT(false); - }; void torrent::connect_to_url_seed(std::string const& url) { INVARIANT_CHECK; -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING (*m_ses.m_logger) << time_now_string() << " resolving web seed: " << url << "\n"; #endif @@ -1662,30 +2018,27 @@ namespace libtorrent std::string hostname; int port; std::string path; + char const* error; + boost::tie(protocol, auth, hostname, port, path, error) + = parse_url_components(url); - try + if (error) { - boost::tie(protocol, auth, hostname, port, path) - = parse_url_components(url); - } - catch (std::exception& e) - { - if (m_ses.m_alerts.should_post(alert::warning)) - { - m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, e.what())); - } +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING + (*m_ses.m_logger) << time_now_string() << " failed to parse web seed url: " << error << "\n"; +#endif + // never try it again remove_url_seed(url); return; } - + #ifdef TORRENT_USE_OPENSSL if (protocol != "http" && protocol != "https") #else if (protocol != "http") #endif { - if (m_ses.m_alerts.should_post(alert::warning)) + if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( url_seed_alert(get_handle(), url, "unknown protocol")); @@ -1697,7 +2050,7 @@ namespace libtorrent if (hostname.empty()) { - if (m_ses.m_alerts.should_post(alert::warning)) + if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( url_seed_alert(get_handle(), url, "invalid hostname")); @@ -1709,7 +2062,7 @@ namespace libtorrent if (port == 0) { - if (m_ses.m_alerts.should_post(alert::warning)) + if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( url_seed_alert(get_handle(), url, "invalid port")); @@ -1727,14 +2080,14 @@ namespace libtorrent // use proxy tcp::resolver::query q(ps.hostname , boost::lexical_cast(ps.port)); - m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( - bind(&torrent::on_proxy_name_lookup, shared_from_this(), _1, _2, url))); + m_host_resolver.async_resolve(q, + bind(&torrent::on_proxy_name_lookup, shared_from_this(), _1, _2, url)); } else { if (m_ses.m_port_filter.access(port) & port_filter::blocked) { - if (m_ses.m_alerts.should_post(alert::warning)) + if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( url_seed_alert(get_handle(), url, "port blocked by port-filter")); @@ -1745,32 +2098,30 @@ namespace libtorrent } tcp::resolver::query q(hostname, boost::lexical_cast(port)); - m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( + m_host_resolver.async_resolve(q, bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url - , tcp::endpoint()))); + , tcp::endpoint())); } } - void torrent::on_proxy_name_lookup(asio::error_code const& e, tcp::resolver::iterator host - , std::string url) try + void torrent::on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator host + , std::string url) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); INVARIANT_CHECK; -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING (*m_ses.m_logger) << time_now_string() << " completed resolve proxy hostname for: " << url << "\n"; #endif if (e || host == tcp::resolver::iterator()) { - if (m_ses.m_alerts.should_post(alert::warning)) + if (m_ses.m_alerts.should_post()) { - std::stringstream msg; - msg << "HTTP seed proxy hostname lookup failed: " << e.message(); m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, msg.str())); + url_seed_alert(get_handle(), url, e.message())); } // the name lookup failed for the http host. Don't try @@ -1786,17 +2137,16 @@ namespace libtorrent using boost::tuples::ignore; std::string hostname; int port; - try + char const* error; + boost::tie(ignore, ignore, hostname, port, ignore, error) + = parse_url_components(url); + + if (error) { - boost::tie(ignore, ignore, hostname, port, ignore) - = parse_url_components(url); - } - catch (std::exception& e) - { - if (m_ses.m_alerts.should_post(alert::warning)) + if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, e.what())); + url_seed_alert(get_handle(), url, error)); } remove_url_seed(url); return; @@ -1804,32 +2154,24 @@ namespace libtorrent if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) { - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(peer_blocked_alert(a.address() - , "proxy (" + hostname + ") blocked by IP filter")); - } - remove_url_seed(url); + if (m_ses.m_alerts.should_post()) + m_ses.m_alerts.post_alert(peer_blocked_alert(a.address())); return; } tcp::resolver::query q(hostname, boost::lexical_cast(port)); - m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( - bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url, a))); + m_host_resolver.async_resolve(q, + bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url, a)); } - catch (std::exception&) - { - TORRENT_ASSERT(false); - }; - void torrent::on_name_lookup(asio::error_code const& e, tcp::resolver::iterator host - , std::string url, tcp::endpoint proxy) try + void torrent::on_name_lookup(error_code const& e, tcp::resolver::iterator host + , std::string url, tcp::endpoint proxy) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); INVARIANT_CHECK; -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING (*m_ses.m_logger) << time_now_string() << " completed resolve: " << url << "\n"; #endif @@ -1838,14 +2180,14 @@ namespace libtorrent if (e || host == tcp::resolver::iterator()) { - if (m_ses.m_alerts.should_post(alert::warning)) + if (m_ses.m_alerts.should_post()) { std::stringstream msg; msg << "HTTP seed hostname lookup failed: " << e.message(); m_ses.m_alerts.post_alert( url_seed_alert(get_handle(), url, msg.str())); } -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING (*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << url << "\n"; #endif @@ -1861,15 +2203,13 @@ namespace libtorrent if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) { - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(peer_blocked_alert(a.address() - , "web seed (" + url + ") blocked by IP filter")); - } + if (m_ses.m_alerts.should_post()) + m_ses.m_alerts.post_alert(peer_blocked_alert(a.address())); return; } - boost::shared_ptr s(new socket_type); + boost::shared_ptr s(new (std::nothrow) socket_type(m_ses.m_io_service)); + if (!s) return; bool ret = instantiate_connection(m_ses.m_io_service, m_ses.web_seed_proxy(), *s); TORRENT_ASSERT(ret); @@ -1881,8 +2221,15 @@ namespace libtorrent // the proxy, without requiring CONNECT support s->get().set_no_connect(true); } - boost::intrusive_ptr c(new web_peer_connection( + + std::pair const& out_ports = m_settings.outgoing_ports; + error_code ec; + if (out_ports.first > 0 && out_ports.second >= out_ports.first) + s->bind(tcp::endpoint(address(), m_ses.next_port()), ec); + + boost::intrusive_ptr c(new (std::nothrow) web_peer_connection( m_ses, shared_from_this(), s, a, url, 0)); + if (!c) return; #ifndef NDEBUG c->m_in_constructor = false; @@ -1897,37 +2244,34 @@ namespace libtorrent } #endif + // add the newly connected peer to this torrent's peer list + m_connections.insert(boost::get_pointer(c)); + m_ses.m_connections.insert(c); + +#ifndef BOOST_NO_EXCEPTIONS try { +#endif // add the newly connected peer to this torrent's peer list m_connections.insert(boost::get_pointer(c)); m_ses.m_connections.insert(c); + c->start(); m_ses.m_half_open.enqueue( bind(&peer_connection::connect, c, _1) , bind(&peer_connection::timed_out, c) , seconds(settings().peer_connect_timeout)); +#ifndef BOOST_NO_EXCEPTIONS } catch (std::exception& e) { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING (*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << e.what() << "\n"; #endif - - // TODO: post an error alert! -// std::map::iterator i = m_connections.find(a); -// if (i != m_connections.end()) m_connections.erase(i); - m_ses.connection_failed(c, a, e.what()); - c->disconnect(); + c->disconnect(e.what(), 1); } - } - catch (std::exception& exc) - { -#ifndef NDEBUG - std::cerr << exc.what() << std::endl; #endif - TORRENT_ASSERT(false); - }; + } #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES namespace @@ -1950,8 +2294,8 @@ namespace libtorrent m_resolving_country = true; asio::ip::address_v4 reversed(swap_bytes(p->remote().address().to_v4().to_ulong())); tcp::resolver::query q(reversed.to_string() + ".zz.countries.nerd.dk", "0"); - m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( - bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p))); + m_host_resolver.async_resolve(q, + bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p)); } namespace @@ -1963,7 +2307,7 @@ namespace libtorrent }; } - void torrent::on_country_lookup(asio::error_code const& error, tcp::resolver::iterator i + void torrent::on_country_lookup(error_code const& error, tcp::resolver::iterator i , intrusive_ptr p) const { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); @@ -2051,7 +2395,7 @@ namespace libtorrent { // unknown country! p->set_country("!!"); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING (*m_ses.m_logger) << "IP " << p->remote().address() << " was mapped to unknown country: " << country << "\n"; #endif return; @@ -2062,6 +2406,159 @@ namespace libtorrent } #endif + void torrent::read_resume_data(lazy_entry const& rd) + { + m_total_uploaded = rd.dict_find_int_value("total_uploaded"); + m_total_downloaded = rd.dict_find_int_value("total_downloaded"); + m_active_time = seconds(rd.dict_find_int_value("active_time")); + m_seeding_time = seconds(rd.dict_find_int_value("seeding_time")); + m_complete = rd.dict_find_int_value("num_seeds", -1); + m_incomplete = rd.dict_find_int_value("num_downloaders", -1); + } + + void torrent::write_resume_data(entry& ret) const + { + ret["file-format"] = "libtorrent resume file"; + ret["file-version"] = 1; + + ret["total_uploaded"] = m_total_uploaded; + ret["total_downloaded"] = m_total_downloaded; + + ret["active_time"] = total_seconds(m_active_time); + ret["seeding_time"] = total_seconds(m_seeding_time); + + int seeds = 0; + int downloaders = 0; + if (m_complete >= 0) seeds = m_complete; + else seeds = m_policy.num_seeds(); + if (m_incomplete >= 0) downloaders = m_incomplete; + else downloaders = m_policy.num_peers() - m_policy.num_seeds(); + + ret["num_seeds"] = seeds; + ret["num_downloaders"] = downloaders; + + const sha1_hash& info_hash = torrent_file().info_hash(); + ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end()); + + // blocks per piece + int num_blocks_per_piece = + static_cast(torrent_file().piece_length()) / block_size(); + ret["blocks per piece"] = num_blocks_per_piece; + + // if this torrent is a seed, we won't have a piece picker + // and there will be no half-finished pieces. + if (!is_seed()) + { + const std::vector& q + = m_picker->get_download_queue(); + + // unfinished pieces + ret["unfinished"] = entry::list_type(); + entry::list_type& up = ret["unfinished"].list(); + + // info for each unfinished piece + for (std::vector::const_iterator i + = q.begin(); i != q.end(); ++i) + { + if (i->finished == 0) continue; + + entry piece_struct(entry::dictionary_t); + + // the unfinished piece's index + piece_struct["piece"] = i->index; + + std::string bitmask; + const int num_bitmask_bytes + = (std::max)(num_blocks_per_piece / 8, 1); + + for (int j = 0; j < num_bitmask_bytes; ++j) + { + unsigned char v = 0; + int bits = (std::min)(num_blocks_per_piece - j*8, 8); + for (int k = 0; k < bits; ++k) + v |= (i->info[j*8+k].state == piece_picker::block_info::state_finished) + ? (1 << k) : 0; + bitmask.insert(bitmask.end(), v); + TORRENT_ASSERT(bits == 8 || j == num_bitmask_bytes - 1); + } + piece_struct["bitmask"] = bitmask; + // push the struct onto the unfinished-piece list + up.push_back(piece_struct); + } + } + + // write have bitmask + entry::string_type& pieces = ret["pieces"].string(); + pieces.resize(m_torrent_file->num_pieces()); + if (is_seed()) + { + for (int i = 0, end(pieces.size()); i < end; ++i) + pieces[i] = 1; + } + else + { + for (int i = 0, end(pieces.size()); i < end; ++i) + pieces[i] = m_picker->have_piece(i) ? 1 : 0; + } + + // write local peers + + entry::list_type& peer_list = ret["peers"].list(); + entry::list_type& banned_peer_list = ret["banned_peers"].list(); + + int max_failcount = m_ses.m_settings.max_failcount; + + for (policy::const_iterator i = m_policy.begin_peer() + , end(m_policy.end_peer()); i != end; ++i) + { + error_code ec; + if (i->second.banned) + { + tcp::endpoint ip = i->second.ip; + entry peer(entry::dictionary_t); + peer["ip"] = ip.address().to_string(ec); + if (ec) continue; + peer["port"] = ip.port(); + banned_peer_list.push_back(peer); + continue; + } + // we cannot save remote connection + // since we don't know their listen port + // unless they gave us their listen port + // through the extension handshake + // so, if the peer is not connectable (i.e. we + // don't know its listen port) or if it has + // been banned, don't save it. + if (i->second.type == policy::peer::not_connectable) continue; + + // don't save peers that doesn't work + if (i->second.failcount >= max_failcount) continue; + + tcp::endpoint ip = i->second.ip; + entry peer(entry::dictionary_t); + peer["ip"] = ip.address().to_string(ec); + if (ec) continue; + peer["port"] = ip.port(); + peer_list.push_back(peer); + } + } + + void torrent::get_full_peer_list(std::vector& v) const + { + v.clear(); + v.reserve(m_policy.num_peers()); + for (policy::const_iterator i = m_policy.begin_peer(); + i != m_policy.end_peer(); ++i) + { + peer_list_entry e; + e.ip = i->second.ip; + e.flags = i->second.banned ? peer_list_entry::banned : 0; + e.failcount = i->second.failcount; + e.source = i->second.source; + v.push_back(e); + } + } + void torrent::get_peer_info(std::vector& v) { v.clear(); @@ -2162,6 +2659,7 @@ namespace libtorrent TORRENT_ASSERT(peerinfo); TORRENT_ASSERT(peerinfo->connection == 0); + peerinfo->connected = time_now(); #ifndef NDEBUG // this asserts that we don't have duplicates in the policy's peer list @@ -2177,10 +2675,14 @@ namespace libtorrent tcp::endpoint const& a(peerinfo->ip); TORRENT_ASSERT((m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) == 0); - boost::shared_ptr s(new socket_type); + boost::shared_ptr s(new socket_type(m_ses.m_io_service)); bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s); TORRENT_ASSERT(ret); + std::pair const& out_ports = m_ses.settings().outgoing_ports; + error_code ec; + if (out_ports.first > 0 && out_ports.second >= out_ports.first) + s->bind(tcp::endpoint(address(), m_ses.next_port()), ec); boost::intrusive_ptr c(new bt_peer_connection( m_ses, shared_from_this(), s, a, peerinfo)); @@ -2189,100 +2691,117 @@ namespace libtorrent c->m_in_constructor = false; #endif - try - { + c->add_stat(peerinfo->prev_amount_download, peerinfo->prev_amount_upload); + peerinfo->prev_amount_download = 0; + peerinfo->prev_amount_upload = 0; + #ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { + for (extension_list_t::iterator i = m_extensions.begin() + , end(m_extensions.end()); i != end; ++i) + { +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif boost::shared_ptr pp((*i)->new_connection(c.get())); if (pp) c->add_extension(pp); - } +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception&) {} +#endif + } #endif - // add the newly connected peer to this torrent's peer list - m_connections.insert(boost::get_pointer(c)); - m_ses.m_connections.insert(c); + // add the newly connected peer to this torrent's peer list + m_connections.insert(boost::get_pointer(c)); + m_ses.m_connections.insert(c); + peerinfo->connection = c.get(); + c->start(); - int timeout = settings().peer_connect_timeout; - if (peerinfo) timeout += 3 * peerinfo->failcount; + int timeout = settings().peer_connect_timeout; + if (peerinfo) timeout += 3 * peerinfo->failcount; +#ifndef BOOST_NO_EXCEPTIONS + try + { +#endif m_ses.m_half_open.enqueue( bind(&peer_connection::connect, c, _1) , bind(&peer_connection::timed_out, c) , seconds(timeout)); +#ifndef BOOST_NO_EXCEPTIONS } catch (std::exception& e) { std::set::iterator i = m_connections.find(boost::get_pointer(c)); if (i != m_connections.end()) m_connections.erase(i); - m_ses.connection_failed(c, a, e.what()); - c->disconnect(); + c->disconnect(e.what()); return false; } - peerinfo->connection = c.get(); +#endif return true; } - void torrent::set_metadata(entry const& metadata) + bool torrent::set_metadata(lazy_entry const& metadata, std::string& error) { INVARIANT_CHECK; TORRENT_ASSERT(!m_torrent_file->is_valid()); - m_torrent_file->parse_info_section(metadata); + if (!m_torrent_file->parse_info_section(metadata, error)) + { + // parse failed + return false; + } + + if (m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(metadata_received_alert( + get_handle())); + } init(); - boost::mutex::scoped_lock(m_checker.m_mutex); - - boost::shared_ptr d( - new aux::piece_checker_data); - d->torrent_ptr = shared_from_this(); - d->save_path = m_save_path; - d->info_hash = m_torrent_file->info_hash(); - // add the torrent to the queue to be checked - m_checker.m_torrents.push_back(d); - typedef session_impl::torrent_map torrent_map; - torrent_map::iterator i = m_ses.m_torrents.find( - m_torrent_file->info_hash()); - TORRENT_ASSERT(i != m_ses.m_torrents.end()); - m_ses.m_torrents.erase(i); - // and notify the thread that it got another - // job in its queue - m_checker.m_cond.notify_one(); - - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(metadata_received_alert( - get_handle(), "metadata successfully received from swarm")); - } + return true; } - void torrent::attach_peer(peer_connection* p) + bool torrent::attach_peer(peer_connection* p) { // INVARIANT_CHECK; TORRENT_ASSERT(p != 0); TORRENT_ASSERT(!p->is_local()); + m_has_incoming = true; + + if ((m_state == torrent_status::queued_for_checking + || m_state == torrent_status::checking_files) + && valid_metadata()) + { + p->disconnect("torrent is not ready to accept peers"); + return false; + } + if (m_ses.m_connections.find(p) == m_ses.m_connections.end()) { - throw protocol_error("peer is not properly constructed"); + p->disconnect("peer is not properly constructed"); + return false; } if (m_ses.is_aborted()) { - throw protocol_error("session is closing"); + p->disconnect("session is closing"); + return false; } if (int(m_connections.size()) >= m_max_connections) { - throw protocol_error("reached connection limit"); + p->disconnect("reached connection limit"); + return false; } +#ifndef BOOST_NO_EXCEPTIONS try { +#endif #ifndef TORRENT_DISABLE_EXTENSIONS for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) @@ -2291,26 +2810,41 @@ namespace libtorrent if (pp) p->add_extension(pp); } #endif - m_policy.new_connection(*p); + if (!m_policy.new_connection(*p)) + return false; +#ifndef BOOST_NO_EXCEPTIONS } - catch (std::exception&) + catch (std::exception& e) { - throw; +#if defined TORRENT_LOGGING + (*m_ses.m_logger) << time_now_string() << " CLOSING CONNECTION " + << p->remote() << " policy::new_connection threw: " << e.what() << "\n"; +#endif + p->disconnect(e.what()); + return false; } +#endif TORRENT_ASSERT(m_connections.find(p) == m_connections.end()); peer_iterator ci = m_connections.insert(p).first; - TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint()); - #ifndef NDEBUG + error_code ec; + TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint(ec) || ec); +#endif + +#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS m_policy.check_invariant(); #endif + return true; } bool torrent::want_more_peers() const { return int(m_connections.size()) < m_max_connections - && m_ses.m_half_open.free_slots() - && !m_paused; + && !is_paused() + && m_state != torrent_status::checking_files + && (m_state != torrent_status::queued_for_checking + || !valid_metadata()) + && m_policy.num_connect_candidates() > 0; } void torrent::disconnect_all() @@ -2324,7 +2858,7 @@ namespace libtorrent peer_connection* p = *m_connections.begin(); TORRENT_ASSERT(p->associated_torrent().lock().get() == this); -#if defined(TORRENT_VERBOSE_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING if (m_abort) (*p->m_logger) << "*** CLOSING CONNECTION 'aborting'\n"; else @@ -2333,27 +2867,99 @@ namespace libtorrent #ifndef NDEBUG std::size_t size = m_connections.size(); #endif - if (p->is_disconnecting()) m_connections.erase(m_connections.begin()); else - p->disconnect(); + p->disconnect(m_abort?"stopping torrent":"pausing torrent"); TORRENT_ASSERT(m_connections.size() <= size); } } + namespace + { + // this returns true if lhs is a better disconnect candidate than rhs + bool compare_disconnect_peer(peer_connection const* lhs, peer_connection const* rhs) + { + // prefer to disconnect peers we're not interested in + if (lhs->is_interesting() != rhs->is_interesting()) + return rhs->is_interesting(); + + // prefer to disconnect peers that are not seeds + if (lhs->is_seed() != rhs->is_seed()) + return rhs->is_seed(); + + // prefer to disconnect peers that are on parole + if (lhs->on_parole() != rhs->on_parole()) + return lhs->on_parole(); + + // prefer to disconnect peers that send data at a lower rate + size_type lhs_transferred = lhs->statistics().total_payload_download(); + size_type rhs_transferred = rhs->statistics().total_payload_download(); + + if (lhs_transferred != rhs_transferred + && lhs_transferred > 0 + && rhs_transferred > 0) + { + ptime now = time_now(); + size_type lhs_time_connected = total_seconds(now - lhs->connected_time()); + size_type rhs_time_connected = total_seconds(now - rhs->connected_time()); + + double lhs_rate = double(lhs_transferred) / (lhs_time_connected + 1); + double rhs_rate = double(rhs_transferred) / (rhs_time_connected + 1); + + return lhs_rate < rhs_rate; + } + + // prefer to disconnect peers that chokes us + if (lhs->is_choked() != rhs->is_choked()) + return lhs->is_choked(); + + return lhs->last_received() < rhs->last_received(); + } + } + + int torrent::disconnect_peers(int num) + { + int ret = 0; + // buils a list of all connected peers and sort it by 'disconnectability'. + std::vector peers(m_connections.size()); + std::copy(m_connections.begin(), m_connections.end(), peers.begin()); + std::sort(peers.begin(), peers.end(), boost::bind(&compare_disconnect_peer, _1, _2)); + + // never disconnect peers that connected less than 90 seconds ago + ptime cut_off = time_now() - seconds(90); + + for (std::vector::iterator i = peers.begin() + , end(peers.end()); i != end && ret < num; ++i) + { + peer_connection* p = *i; + if (p->connected_time() > cut_off) continue; + ++ret; + p->disconnect("optimistic disconnect"); + } + return ret; + } + int torrent::bandwidth_throttle(int channel) const { return m_bandwidth_limit[channel].throttle(); } + int torrent::bandwidth_queue_size(int channel) const + { + return (int)m_bandwidth_queue[channel].size(); + } + void torrent::request_bandwidth(int channel , boost::intrusive_ptr const& p - , int priority) + , int max_block_size, int priority) { + TORRENT_ASSERT(max_block_size > 0); TORRENT_ASSERT(m_bandwidth_limit[channel].throttle() > 0); TORRENT_ASSERT(p->max_assignable_bandwidth(channel) > 0); - int block_size = m_bandwidth_limit[channel].throttle() / 10; + TORRENT_ASSERT(p->m_channel_state[channel] == peer_info::bw_torrent); + int block_size = (std::min)(m_bandwidth_limit[channel].throttle() / 10 + , max_block_size); if (block_size <= 0) block_size = 1; if (m_bandwidth_limit[channel].max_assignable() > 0) @@ -2379,6 +2985,8 @@ namespace libtorrent { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); + INVARIANT_CHECK; + TORRENT_ASSERT(amount > 0); m_bandwidth_limit[channel].expire(amount); queue_t tmp; @@ -2405,6 +3013,8 @@ namespace libtorrent , int block_size , int priority) { + TORRENT_ASSERT(p->m_channel_state[channel] == peer_info::bw_torrent); + p->m_channel_state[channel] = peer_info::bw_global; m_ses.m_bandwidth_manager[channel]->request_bandwidth(p , block_size, priority); m_bandwidth_limit[channel].assign(block_size); @@ -2426,13 +3036,20 @@ namespace libtorrent { INVARIANT_CHECK; - if (alerts().should_post(alert::info)) + if (alerts().should_post()) { alerts().post_alert(torrent_finished_alert( - get_handle() - , "torrent has finished downloading")); + get_handle())); } + set_state(torrent_status::finished); + set_queue_position(-1); + + // we have to call completed() before we start + // disconnecting peers, since there's an assert + // to make sure we're cleared the piece picker + if (is_seed()) completed(); + // disconnect all seeds // TODO: should disconnect all peers that have the pieces we have // not just seeds @@ -2442,31 +3059,45 @@ namespace libtorrent { peer_connection* p = *i; TORRENT_ASSERT(p->associated_torrent().lock().get() == this); - if (p->is_seed()) + if (p->upload_only()) { -#if defined(TORRENT_VERBOSE_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*p->m_logger) << "*** SEED, CLOSING CONNECTION\n"; #endif seeds.push_back(p); } } std::for_each(seeds.begin(), seeds.end() - , bind(&peer_connection::disconnect, _1)); + , bind(&peer_connection::disconnect, _1, "torrent finished, disconnecting seed", 0)); TORRENT_ASSERT(m_storage); // we need to keep the object alive during this operation m_storage->async_release_files( bind(&torrent::on_files_released, shared_from_this(), _1, _2)); } + + // this is called when we were finished, but some files were + // marked for downloading, and we are no longer finished + void torrent::resume_download() + { + INVARIANT_CHECK; + TORRENT_ASSERT(!is_finished()); + set_state(torrent_status::downloading); + set_queue_position((std::numeric_limits::max)()); + } + // called when torrent is complete (all pieces downloaded) void torrent::completed() { INVARIANT_CHECK; + m_picker.reset(); + // make the next tracker request // be a completed-event m_event = tracker_request::completed; + set_state(torrent_status::seeding); force_tracker_request(); } @@ -2497,7 +3128,7 @@ namespace libtorrent if ((unsigned)m_currently_trying_tracker >= m_trackers.size()) { int delay = tracker_retry_delay_min - + (std::min)(m_failed_trackers, (int)tracker_failed_max) + + (std::min)(int(m_failed_trackers), int(tracker_failed_max)) * (tracker_retry_delay_max - tracker_retry_delay_min) / tracker_failed_max; @@ -2518,7 +3149,7 @@ namespace libtorrent boost::weak_ptr self(shared_from_this()); m_ses.m_dht->announce(m_torrent_file->info_hash() , m_ses.m_listen_sockets.front().external_port - , m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1))); + , bind(&torrent::on_dht_announce_response_disp, self, _1)); } #endif @@ -2531,121 +3162,41 @@ namespace libtorrent } - bool torrent::check_fastresume(aux::piece_checker_data& data) - { - INVARIANT_CHECK; - - TORRENT_ASSERT(valid_metadata()); - bool done = true; - try - { - std::string error_msg; - TORRENT_ASSERT(m_storage); - TORRENT_ASSERT(m_owning_storage.get()); - done = m_storage->check_fastresume(data, m_have_pieces, m_num_pieces - , m_storage_mode, error_msg); - - if (!error_msg.empty() && m_ses.m_alerts.should_post(alert::warning)) - { - m_ses.m_alerts.post_alert(fastresume_rejected_alert( - get_handle(), error_msg)); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "fastresume data for " - << torrent_file().name() << " rejected: " - << error_msg << "\n"; -#endif - } - } - catch (std::exception& e) - { - // probably means file permission failure or invalid filename - std::fill(m_have_pieces.begin(), m_have_pieces.end(), false); - m_num_pieces = 0; - - if (m_ses.m_alerts.should_post(alert::fatal)) - { - m_ses.m_alerts.post_alert( - file_error_alert( - get_handle() - , e.what())); - } - pause(); - } - return done; - } - - std::pair torrent::check_files() - { - TORRENT_ASSERT(m_torrent_file->is_valid()); - INVARIANT_CHECK; - - TORRENT_ASSERT(m_owning_storage.get()); - - std::pair progress(true, 1.f); - try - { - TORRENT_ASSERT(m_storage); - progress = m_storage->check_files(m_have_pieces, m_num_pieces - , m_ses.m_mutex); - } - catch (std::exception& e) - { - // probably means file permission failure or invalid filename - std::fill(m_have_pieces.begin(), m_have_pieces.end(), false); - m_num_pieces = 0; - - if (m_ses.m_alerts.should_post(alert::fatal)) - { - m_ses.m_alerts.post_alert( - file_error_alert( - get_handle() - , e.what())); - } - pause(); - } - - return progress; - } - - void torrent::files_checked(std::vector const& - unfinished_pieces) + void torrent::files_checked() { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); TORRENT_ASSERT(m_torrent_file->is_valid()); INVARIANT_CHECK; + set_state(torrent_status::connecting_to_tracker); + if (!is_seed()) { - // this is filled in with pieces that needs to be checked - // against its hashes. - std::vector verify_pieces; - m_picker->files_checked(m_have_pieces, unfinished_pieces, verify_pieces); - if (m_sequenced_download_threshold > 0) - picker().set_sequenced_download_threshold(m_sequenced_download_threshold); - while (!verify_pieces.empty()) - { - int piece = verify_pieces.back(); - verify_pieces.pop_back(); - async_verify_piece(piece, bind(&torrent::piece_finished - , shared_from_this(), piece, _1)); - } + if (m_sequential_download) + picker().sequential_download(m_sequential_download); + + // if we just finished checking and we're not a seed, we are + // likely to be unpaused + if (m_ses.m_auto_manage_time_scaler > 1) + m_ses.m_auto_manage_time_scaler = 1; } #ifndef TORRENT_DISABLE_EXTENSIONS for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) { - try { (*i)->on_files_checked(); } catch (std::exception&) {} +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + (*i)->on_files_checked(); +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception&) {} +#endif } #endif - if (is_seed()) - { - m_picker.reset(); - if (m_ses.settings().free_torrent_hashes) - m_torrent_file->seed_free(); - } + if (is_seed()) finished(); if (!m_connections_initialized) { @@ -2655,25 +3206,31 @@ namespace libtorrent for (torrent::peer_iterator i = m_connections.begin() , end(m_connections.end()); i != end;) { + boost::intrusive_ptr pc = *i; + ++i; +#ifndef BOOST_NO_EXCEPTIONS try { - (*i)->on_metadata(); - (*i)->init(); - ++i; +#endif + pc->on_metadata(); + pc->init(); +#ifndef BOOST_NO_EXCEPTIONS } catch (std::exception& e) { - // the connection failed, close it - torrent::peer_iterator j = i; - ++j; - m_ses.connection_failed(*i, (*i)->remote(), e.what()); - i = j; + pc->disconnect(e.what()); } +#endif } } -#ifndef NDEBUG + + if (m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(torrent_checked_alert( + get_handle())); + } + m_files_checked = true; -#endif } alert_manager& torrent::alerts() const @@ -2683,10 +3240,21 @@ namespace libtorrent fs::path torrent::save_path() const { - if (m_owning_storage.get()) - return m_owning_storage->save_path(); - else - return m_save_path; + return m_save_path; + } + + bool torrent::rename_file(int index, std::string const& name) + { + INVARIANT_CHECK; + + TORRENT_ASSERT(index >= 0); + TORRENT_ASSERT(index < m_torrent_file->num_files()); + + if (!m_owning_storage.get()) return false; + + m_owning_storage->async_rename_file(index, name + , bind(&torrent::on_file_renamed, shared_from_this(), _1, _2)); + return true; } void torrent::move_storage(fs::path const& save_path) @@ -2708,22 +3276,24 @@ namespace libtorrent { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - if (alerts().should_post(alert::warning)) + if (alerts().should_post()) { alerts().post_alert(storage_moved_alert(get_handle(), j.str)); } + m_save_path = j.str; } piece_manager& torrent::filesystem() { TORRENT_ASSERT(m_owning_storage.get()); - return *m_owning_storage; + TORRENT_ASSERT(m_storage); + return *m_storage; } - torrent_handle torrent::get_handle() const + torrent_handle torrent::get_handle() { - return torrent_handle(&m_ses, &m_checker, m_torrent_file->info_hash()); + return torrent_handle(shared_from_this()); } session_settings const& torrent::settings() const @@ -2736,6 +3306,9 @@ namespace libtorrent { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); + TORRENT_ASSERT(m_resume_entry.type() == lazy_entry::dict_t + || m_resume_entry.type() == lazy_entry::none_t); + TORRENT_ASSERT(m_bandwidth_queue[0].size() <= m_connections.size()); TORRENT_ASSERT(m_bandwidth_queue[1].size() <= m_connections.size()); @@ -2753,13 +3326,15 @@ namespace libtorrent std::map num_requests; for (const_peer_iterator i = begin(); i != end(); ++i) { + // make sure this peer is not a dangling pointer + TORRENT_ASSERT(m_ses.has_peer(*i)); peer_connection const& p = *(*i); for (std::deque::const_iterator i = p.request_queue().begin() , end(p.request_queue().end()); i != end; ++i) ++num_requests[*i]; - for (std::deque::const_iterator i = p.download_queue().begin() + for (std::deque::const_iterator i = p.download_queue().begin() , end(p.download_queue().end()); i != end; ++i) - ++num_requests[*i]; + ++num_requests[i->block]; if (!p.is_choked()) ++num_uploads; torrent* associated_torrent = p.associated_torrent().lock().get(); if (associated_torrent != this) @@ -2775,15 +3350,16 @@ namespace libtorrent if (!m_picker->is_downloaded(i->first)) TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second); } + TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered()); } if (valid_metadata()) { - TORRENT_ASSERT(m_abort || int(m_have_pieces.size()) == m_torrent_file->num_pieces()); + TORRENT_ASSERT(m_abort || !m_picker || m_picker->num_pieces() == m_torrent_file->num_pieces()); } else { - TORRENT_ASSERT(m_abort || m_have_pieces.empty()); + TORRENT_ASSERT(m_abort || m_picker->num_pieces() == 0); } for (policy::const_iterator i = m_policy.begin_peer() @@ -2798,7 +3374,9 @@ namespace libtorrent if (is_seed()) TORRENT_ASSERT(total_done == m_torrent_file->total_size()); else - TORRENT_ASSERT(total_done != m_torrent_file->total_size()); + TORRENT_ASSERT(total_done != m_torrent_file->total_size() || !m_files_checked); + + TORRENT_ASSERT(m_block_size <= m_torrent_file->piece_length()); } else { @@ -2825,37 +3403,98 @@ namespace libtorrent complete = false; break; } - if (complete && m_files_checked) - { - disk_io_job ret = m_ses.m_disk_thread.find_job( - m_owning_storage, -1, i->index); - TORRENT_ASSERT(ret.action == disk_io_job::hash || ret.action == disk_io_job::write); - TORRENT_ASSERT(ret.piece == i->index); - } } } // This check is very expensive. - TORRENT_ASSERT(m_num_pieces - == std::count(m_have_pieces.begin(), m_have_pieces.end(), true)); TORRENT_ASSERT(!valid_metadata() || m_block_size > 0); TORRENT_ASSERT(!valid_metadata() || (m_torrent_file->piece_length() % m_block_size) == 0); // if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0); } #endif - void torrent::set_sequenced_download_threshold(int threshold) + void torrent::set_sequential_download(bool sd) { if (has_picker()) { - picker().set_sequenced_download_threshold(threshold); + picker().sequential_download(sd); } else { - m_sequenced_download_threshold = threshold; + m_sequential_download = sd; } } + void torrent::set_queue_position(int p) + { + TORRENT_ASSERT((p == -1) == is_finished() + || (!m_auto_managed && p == -1) + || (m_abort && p == -1)); + if (is_finished() && p != -1) return; + if (p == m_sequence_number) return; + + session_impl::torrent_map& torrents = m_ses.m_torrents; + if (p >= 0 && m_sequence_number == -1) + { + int max_seq = -1; + for (session_impl::torrent_map::iterator i = torrents.begin() + , end(torrents.end()); i != end; ++i) + { + torrent* t = i->second.get(); + if (t->m_sequence_number > max_seq) max_seq = t->m_sequence_number; + } + m_sequence_number = (std::min)(max_seq + 1, p); + } + else if (p < 0) + { + for (session_impl::torrent_map::iterator i = torrents.begin() + , end(torrents.end()); i != end; ++i) + { + torrent* t = i->second.get(); + if (t == this) continue; + if (t->m_sequence_number >= m_sequence_number + && t->m_sequence_number != -1) + --t->m_sequence_number; + } + m_sequence_number = p; + } + else if (p < m_sequence_number) + { + for (session_impl::torrent_map::iterator i = torrents.begin() + , end(torrents.end()); i != end; ++i) + { + torrent* t = i->second.get(); + if (t == this) continue; + if (t->m_sequence_number >= p + && t->m_sequence_number < m_sequence_number + && t->m_sequence_number != -1) + ++t->m_sequence_number; + } + m_sequence_number = p; + } + else if (p > m_sequence_number) + { + int max_seq = 0; + for (session_impl::torrent_map::iterator i = torrents.begin() + , end(torrents.end()); i != end; ++i) + { + torrent* t = i->second.get(); + int pos = t->m_sequence_number; + if (pos > max_seq) max_seq = pos; + if (t == this) continue; + + if (pos <= p + && pos > m_sequence_number + && pos != -1) + --t->m_sequence_number; + + } + m_sequence_number = (std::min)(max_seq, p); + } + + if (m_ses.m_auto_manage_time_scaler > 2) + m_ses.m_auto_manage_time_scaler = 2; + } void torrent::set_max_uploads(int limit) { @@ -2921,7 +3560,7 @@ namespace libtorrent void torrent::delete_files() { -#if defined(TORRENT_VERBOSE_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) { @@ -2930,7 +3569,7 @@ namespace libtorrent #endif disconnect_all(); - if (!m_paused) + if (!is_paused()) m_just_paused = true; m_paused = true; // tell the tracker that we stopped @@ -2944,21 +3583,141 @@ namespace libtorrent } } + void torrent::auto_managed(bool a) + { + INVARIANT_CHECK; + + if (m_auto_managed == a) return; + m_auto_managed = a; + // recalculate which torrents should be + // paused + m_ses.m_auto_manage_time_scaler = 0; + } + + // the higher seed rank, the more important to seed + int torrent::seed_rank(session_settings const& s) const + { + enum flags + { + seed_ratio_not_met = 0x400000, + recently_started = 0x200000, + no_seeds = 0x100000, + prio_mask = 0xfffff + }; + + if (!is_seed()) return 0; + + int ret = 0; + + ptime now(time_now()); + + int seed_time = total_seconds(m_seeding_time); + int download_time = total_seconds(m_active_time) - seed_time; + + // if we haven't yet met the seed limits, set the seed_ratio_not_met + // flag. That will make this seed prioritized + size_type downloaded = (std::max)(m_total_downloaded, m_torrent_file->total_size()); + if (seed_time < s.seed_time_limit + && (seed_time > 1 && download_time / float(seed_time) < s.seed_time_ratio_limit) + && m_total_uploaded / downloaded < s.share_ratio_limit) + ret |= seed_ratio_not_met; + + // if this torrent is running, and it was started less + // than 30 minutes ago, give it priority, to avoid oscillation + if (!is_paused() && now - m_started < minutes(30)) + ret |= recently_started; + + // if we have any scrape data, use it to calculate + // seed rank + int seeds = 0; + int downloaders = 0; + + if (m_complete >= 0) seeds = m_complete; + else seeds = m_policy.num_seeds(); + + if (m_incomplete >= 0) downloaders = m_incomplete; + else downloaders = m_policy.num_peers() - m_policy.num_seeds(); + + if (seeds == 0) + { + ret |= no_seeds; + ret |= downloaders & prio_mask; + } + else + { + ret |= (downloaders * 100 / seeds) & prio_mask; + } + + return ret; + } + + // this is an async operation triggered by the client + void torrent::save_resume_data() + { + INVARIANT_CHECK; + + if (m_owning_storage.get()) + { + TORRENT_ASSERT(m_storage); + if (m_state == torrent_status::queued_for_checking + || m_state == torrent_status::checking_files) + { + if (alerts().should_post()) + { + alerts().post_alert(save_resume_data_failed_alert(get_handle() + , "won't save resume data, torrent does not have a complete resume state yet")); + } + } + else + { + m_storage->async_save_resume_data( + bind(&torrent::on_save_resume_data, shared_from_this(), _1, _2)); + } + } + else + { + if (alerts().should_post()) + { + alerts().post_alert(save_resume_data_failed_alert(get_handle() + , "save resume data failed, torrent is being destructed")); + } + } + } + + bool torrent::is_paused() const + { + return m_paused || m_ses.is_paused(); + } + void torrent::pause() { INVARIANT_CHECK; if (m_paused) return; + m_paused = true; + if (m_ses.is_paused()) return; + do_pause(); + } + + void torrent::do_pause() + { + if (!is_paused()) return; #ifndef TORRENT_DISABLE_EXTENSIONS for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) { - try { if ((*i)->on_pause()) return; } catch (std::exception&) {} +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + if ((*i)->on_pause()) return; +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception&) {} +#endif } #endif -#if defined(TORRENT_VERBOSE_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) { @@ -2967,7 +3726,6 @@ namespace libtorrent #endif disconnect_all(); - m_paused = true; // tell the tracker that we stopped m_event = tracker_request::stopped; m_just_paused = true; @@ -2981,10 +3739,8 @@ namespace libtorrent } else { - if (alerts().should_post(alert::warning)) - { - alerts().post_alert(torrent_paused_alert(get_handle(), "torrent paused")); - } + if (alerts().should_post()) + alerts().post_alert(torrent_paused_alert(get_handle())); } } @@ -2993,16 +3749,33 @@ namespace libtorrent INVARIANT_CHECK; if (!m_paused) return; + m_paused = false; + do_resume(); + } + + void torrent::do_resume() + { + if (is_paused()) return; #ifndef TORRENT_DISABLE_EXTENSIONS for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) { - try { if ((*i)->on_resume()) return; } catch (std::exception&) {} +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + if ((*i)->on_resume()) return; +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception&) {} +#endif } #endif - m_paused = false; + m_started = time_now(); + m_error.clear(); + + if (alerts().should_post()) + alerts().post_alert(torrent_resumed_alert(get_handle())); // tell the tracker that we're back m_event = tracker_request::started; @@ -3020,7 +3793,13 @@ namespace libtorrent for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) { - try { (*i)->tick(); } catch (std::exception&) {} +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + (*i)->tick(); +#ifndef BOOST_NO_EXCEPTIONS + } catch (std::exception&) {} +#endif } #endif @@ -3031,6 +3810,10 @@ namespace libtorrent return; } + time_duration since_last_tick = microsec(tick_interval * 1000000L); + if (is_seed()) m_seeding_time += since_last_tick; + m_active_time += since_last_tick; + // ---- WEB SEEDS ---- // re-insert urls that are to be retries into the m_web_seeds @@ -3080,24 +3863,29 @@ namespace libtorrent { peer_connection* p = *i; ++i; + p->calc_ip_overhead(); m_stat += p->statistics(); // updates the peer connection's ul/dl bandwidth // resource requests +#ifndef BOOST_NO_EXCEPTIONS try { +#endif p->second_tick(tick_interval); +#ifndef BOOST_NO_EXCEPTIONS } catch (std::exception& e) { - (void)e; -#ifdef TORRENT_VERBOSE_LOGGING +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*p->m_logger) << "**ERROR**: " << e.what() << "\n"; #endif - p->set_failed(); - p->disconnect(); + p->disconnect(e.what(), 1); } +#endif } accumulator += m_stat; + m_total_uploaded += m_stat.last_payload_uploaded(); + m_total_downloaded += m_stat.last_payload_downloaded(); m_stat.second_tick(tick_interval); m_time_scaler--; @@ -3117,10 +3905,21 @@ namespace libtorrent bool torrent::try_connect_peer() { TORRENT_ASSERT(want_more_peers()); - return m_policy.connect_one_peer(); + if (m_deficit_counter < 100) return false; + m_deficit_counter -= 100; + bool ret = m_policy.connect_one_peer(); + return ret; } - void torrent::async_verify_piece(int piece_index, boost::function const& f) + void torrent::give_connect_points(int points) + { + TORRENT_ASSERT(points <= 100); + TORRENT_ASSERT(points > 0); + TORRENT_ASSERT(want_more_peers()); + m_deficit_counter += points; + } + + void torrent::async_verify_piece(int piece_index, boost::function const& f) { // INVARIANT_CHECK; @@ -3128,21 +3927,43 @@ namespace libtorrent TORRENT_ASSERT(m_storage->refcount() > 0); TORRENT_ASSERT(piece_index >= 0); TORRENT_ASSERT(piece_index < m_torrent_file->num_pieces()); - TORRENT_ASSERT(piece_index < (int)m_have_pieces.size()); + TORRENT_ASSERT(piece_index < (int)m_picker->num_pieces()); +#ifndef NDEBUG + if (m_picker) + { + int blocks_in_piece = m_picker->blocks_in_piece(piece_index); + for (int i = 0; i < blocks_in_piece; ++i) + { + TORRENT_ASSERT(m_picker->num_peers(piece_block(piece_index, i)) == 0); + } + } +#endif m_storage->async_hash(piece_index, bind(&torrent::on_piece_verified , shared_from_this(), _1, _2, f)); -#ifndef NDEBUG +#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS check_invariant(); #endif } void torrent::on_piece_verified(int ret, disk_io_job const& j - , boost::function f) + , boost::function f) { - sha1_hash h(j.str); session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - f(m_torrent_file->hash_for_piece(j.piece) == h); + + // return value: + // 0: success, piece passed hash check + // -1: disk failure + // -2: hash check failed + + if (ret == -1) + { + if (alerts().should_post()) + alerts().post_alert(file_error_alert(j.error_file, get_handle(), j.str)); + m_error = j.str; + pause(); + } + f(ret); } const tcp::endpoint& torrent::current_tracker() const @@ -3150,20 +3971,24 @@ namespace libtorrent return m_tracker_address; } - bool torrent::is_allocating() const - { return m_owning_storage.get() && m_owning_storage->is_allocating(); } - void torrent::file_progress(std::vector& fp) const { TORRENT_ASSERT(valid_metadata()); fp.clear(); + if (is_seed()) + { + fp.resize(m_torrent_file->num_files(), 1.f); + return; + } + + TORRENT_ASSERT(has_picker()); fp.resize(m_torrent_file->num_files(), 0.f); for (int i = 0; i < m_torrent_file->num_files(); ++i) { - peer_request ret = m_torrent_file->map_file(i, 0, 0); - size_type size = m_torrent_file->file_at(i).size; + peer_request ret = m_torrent_file->files().map_file(i, 0, 0); + size_type size = m_torrent_file->files().at(i).size; // zero sized files are considered // 100% done all the time @@ -3178,37 +4003,100 @@ namespace libtorrent { size_type bytes_step = (std::min)(size_type(m_torrent_file->piece_size(ret.piece) - ret.start), size); - if (m_have_pieces[ret.piece]) done += bytes_step; + if (m_picker->have_piece(ret.piece)) done += bytes_step; ++ret.piece; ret.start = 0; size -= bytes_step; } TORRENT_ASSERT(size == 0); - fp[i] = static_cast(done) / m_torrent_file->file_at(i).size; + fp[i] = static_cast(done) / m_torrent_file->files().at(i).size; + } + + const std::vector& q + = m_picker->get_download_queue(); + + for (std::vector::const_iterator + i = q.begin(), end(q.end()); i != end; ++i) + { + size_type offset = size_type(i->index) * m_torrent_file->piece_length(); + torrent_info::file_iterator file = m_torrent_file->file_at_offset(offset); + int file_index = file - m_torrent_file->begin_files(); + int num_blocks = m_picker->blocks_in_piece(i->index); + piece_picker::block_info const* info = i->info; + for (int k = 0; k < num_blocks; ++k) + { + if (info[k].state != piece_picker::block_info::state_writing + && info[k].state != piece_picker::block_info::state_finished) + continue; + if (offset + m_block_size > file->offset + file->size) + { + // split the block on multiple files + size_type block_size = m_block_size; + while (offset + block_size > file->offset + file->size) + { + TORRENT_ASSERT(offset <= file->offset + file->size); + size_type slice = file->offset + file->size - offset; + fp[file_index] += float(slice) / file->size; + offset += slice; + block_size -= slice; + ++file; + ++file_index; + if (file == m_torrent_file->end_files()) break; + } + } + else + { + fp[file_index] += float(m_block_size) / file->size; + offset += m_block_size; + } + } } } + void torrent::set_state(torrent_status::state_t s) + { + if (m_state == s) return; + m_state = s; + if (m_ses.m_alerts.should_post()) + m_ses.m_alerts.post_alert(state_changed_alert(get_handle(), s)); + } + torrent_status torrent::status() const { INVARIANT_CHECK; - TORRENT_ASSERT(std::accumulate( - m_have_pieces.begin() - , m_have_pieces.end() - , 0) == m_num_pieces); + ptime now = time_now(); torrent_status st; + st.has_incoming = m_has_incoming; + st.error = m_error; + + if (m_last_scrape == min_time()) + { + st.last_scrape = -1; + } + else + { + st.last_scrape = total_seconds(now - m_last_scrape); + } st.up_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::upload_channel].size(); st.down_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::download_channel].size(); st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end() , !boost::bind(&peer_connection::is_connecting, _1)); - st.list_peers = std::distance(m_policy.begin_peer(), m_policy.end_peer()); - st.list_seeds = (int)std::count_if(m_policy.begin_peer(), m_policy.end_peer() - , boost::bind(&policy::peer::seed, bind(&policy::iterator::value_type::second, _1))); + st.list_peers = m_policy.num_peers(); + st.list_seeds = m_policy.num_seeds(); + st.connect_candidates = m_policy.num_connect_candidates(); + st.seed_rank = seed_rank(m_ses.m_settings); + + st.all_time_upload = m_total_uploaded; + st.all_time_download = m_total_downloaded; + + st.active_time = total_seconds(m_active_time); + st.seeding_time = total_seconds(m_seeding_time); st.storage_mode = m_storage_mode; @@ -3216,6 +4104,7 @@ namespace libtorrent st.num_incomplete = m_incomplete; st.paused = m_paused; boost::tie(st.total_done, st.total_wanted_done) = bytes_done(); + TORRENT_ASSERT(st.total_wanted_done >= 0); TORRENT_ASSERT(st.total_done >= st.total_wanted_done); // payload transfer @@ -3239,7 +4128,7 @@ namespace libtorrent st.upload_payload_rate = m_stat.upload_payload_rate(); st.next_announce = boost::posix_time::seconds( - total_seconds(next_announce() - time_now())); + total_seconds(next_announce() - now)); if (st.next_announce.is_negative()) st.next_announce = boost::posix_time::seconds(0); @@ -3257,21 +4146,17 @@ namespace libtorrent st.connections_limit = m_max_connections; // if we don't have any metadata, stop here + st.state = m_state; + if (!valid_metadata()) { - if (m_got_tracker_response == false) + if (m_got_tracker_response == false && m_connections.empty()) st.state = torrent_status::connecting_to_tracker; else st.state = torrent_status::downloading_metadata; -// TODO: add a progress member to the torrent that will be used in this case -// and that may be set by a plugin -// if (m_metadata_size == 0) st.progress = 0.f; -// else st.progress = (std::min)(1.f, m_metadata_progress / (float)m_metadata_size); - st.progress = 0.f; - + st.progress = m_progress; st.block_size = 0; - return st; } @@ -3280,49 +4165,41 @@ namespace libtorrent // fill in status that depends on metadata st.total_wanted = m_torrent_file->total_size(); + TORRENT_ASSERT(st.total_wanted >= 0); + TORRENT_ASSERT(st.total_wanted >= m_torrent_file->piece_length() + * (m_torrent_file->num_pieces() - 1)); if (m_picker.get() && (m_picker->num_filtered() > 0 || m_picker->num_have_filtered() > 0)) { - int filtered_pieces = m_picker->num_filtered() + int num_filtered_pieces = m_picker->num_filtered() + m_picker->num_have_filtered(); int last_piece_index = m_torrent_file->num_pieces() - 1; if (m_picker->piece_priority(last_piece_index) == 0) { st.total_wanted -= m_torrent_file->piece_size(last_piece_index); - --filtered_pieces; + --num_filtered_pieces; } - st.total_wanted -= size_type(filtered_pieces) * m_torrent_file->piece_length(); + st.total_wanted -= size_type(num_filtered_pieces) * m_torrent_file->piece_length(); } TORRENT_ASSERT(st.total_wanted >= st.total_wanted_done); - if (st.total_wanted == 0) st.progress = 1.f; + if (m_state == torrent_status::checking_files) + st.progress = m_progress; + else if (st.total_wanted == 0) st.progress = 1.f; else st.progress = st.total_wanted_done / static_cast(st.total_wanted); - st.pieces = &m_have_pieces; - st.num_pieces = m_num_pieces; - - if (m_got_tracker_response == false) + if (has_picker()) { - st.state = torrent_status::connecting_to_tracker; + int num_pieces = m_picker->num_pieces(); + st.pieces.resize(num_pieces, false); + for (int i = 0; i < num_pieces; ++i) + if (m_picker->have_piece(i)) st.pieces.set_bit(i); } - else if (is_seed()) - { - TORRENT_ASSERT(st.total_done == m_torrent_file->total_size()); - st.state = torrent_status::seeding; - } - else if (st.total_wanted_done == st.total_wanted) - { - st.state = torrent_status::finished; - } - else - { - st.state = torrent_status::downloading; - } - + st.num_pieces = num_have(); st.num_seeds = num_seeds(); if (m_picker.get()) st.distributed_copies = m_picker->distributed_copies(); @@ -3346,22 +4223,24 @@ namespace libtorrent INVARIANT_CHECK; -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING debug_log("*** tracker timed out"); #endif - if (m_ses.m_alerts.should_post(alert::warning)) + if (r.kind == tracker_request::announce_request) { - std::stringstream s; - s << "tracker: \"" << r.url << "\" timed out"; - if (r.kind == tracker_request::announce_request) + if (m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(tracker_alert(get_handle() - , m_failed_trackers + 1, 0, r.url, s.str())); + m_ses.m_alerts.post_alert(tracker_error_alert(get_handle() + , m_failed_trackers + 1, 0, r.url, "tracker timed out")); } - else if (r.kind == tracker_request::scrape_request) + } + else if (r.kind == tracker_request::scrape_request) + { + if (m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle(), s.str())); + m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle() + , r.url, "tracker timed out")); } } @@ -3379,21 +4258,22 @@ namespace libtorrent INVARIANT_CHECK; -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING debug_log(std::string("*** tracker error: ") + str); #endif - if (m_ses.m_alerts.should_post(alert::warning)) + if (r.kind == tracker_request::announce_request) { - std::stringstream s; - s << "tracker: \"" << r.url << "\" " << str; - if (r.kind == tracker_request::announce_request) + if (m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(tracker_alert(get_handle() - , m_failed_trackers + 1, response_code, r.url, s.str())); + m_ses.m_alerts.post_alert(tracker_error_alert(get_handle() + , m_failed_trackers + 1, response_code, r.url, str)); } - else if (r.kind == tracker_request::scrape_request) + } + else if (r.kind == tracker_request::scrape_request) + { + if (m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle(), s.str())); + m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle(), r.url, str)); } } @@ -3402,7 +4282,7 @@ namespace libtorrent } -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING void torrent::debug_log(const std::string& line) { (*m_ses.m_logger) << time_now_string() << " " << line << "\n"; diff --git a/libtorrent/src/torrent_handle.cpp b/libtorrent/src/torrent_handle.cpp index 4635f4411..31e28e3a6 100755 --- a/libtorrent/src/torrent_handle.cpp +++ b/libtorrent/src/torrent_handle.cpp @@ -81,59 +81,41 @@ using libtorrent::aux::session_impl; #ifdef BOOST_NO_EXCEPTIONS #define TORRENT_FORWARD(call) \ - if (m_ses == 0) return; \ - TORRENT_ASSERT(m_chk); \ - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ - mutex::scoped_lock l2(m_chk->m_mutex); \ - torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ - if (t == 0) return; \ + boost::shared_ptr t = m_torrent.lock(); \ + if (!t) return; \ + session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ t->call #define TORRENT_FORWARD_RETURN(call, def) \ - if (m_ses == 0) return def; \ - TORRENT_ASSERT(m_chk); \ - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ - mutex::scoped_lock l2(m_chk->m_mutex); \ - torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ - if (t == 0) return def; \ + boost::shared_ptr t = m_torrent.lock(); \ + if (!t) return def; \ + session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ return t->call #define TORRENT_FORWARD_RETURN2(call, def) \ - if (m_ses == 0) return def; \ - TORRENT_ASSERT(m_chk); \ - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ - mutex::scoped_lock l2(m_chk->m_mutex); \ - torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ - if (t == 0) return def; \ + boost::shared_ptr t = m_torrent.lock(); \ + if (!t) return def; \ + session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ t->call #else #define TORRENT_FORWARD(call) \ - if (m_ses == 0) throw_invalid_handle(); \ - TORRENT_ASSERT(m_chk); \ - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ - mutex::scoped_lock l2(m_chk->m_mutex); \ - torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ - if (t == 0) throw_invalid_handle(); \ + boost::shared_ptr t = m_torrent.lock(); \ + if (!t) throw_invalid_handle(); \ + session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ t->call #define TORRENT_FORWARD_RETURN(call, def) \ - if (m_ses == 0) throw_invalid_handle(); \ - TORRENT_ASSERT(m_chk); \ - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ - mutex::scoped_lock l2(m_chk->m_mutex); \ - torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ - if (t == 0) return def; \ + boost::shared_ptr t = m_torrent.lock(); \ + if (!t) throw_invalid_handle(); \ + session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ return t->call #define TORRENT_FORWARD_RETURN2(call, def) \ - if (m_ses == 0) throw_invalid_handle(); \ - TORRENT_ASSERT(m_chk); \ - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ - mutex::scoped_lock l2(m_chk->m_mutex); \ - torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ - if (t == 0) return def; \ + boost::shared_ptr t = m_torrent.lock(); \ + if (!t) throw_invalid_handle(); \ + session_impl::mutex_t::scoped_lock l(t->session().m_mutex); \ t->call #endif @@ -150,30 +132,22 @@ namespace libtorrent throw invalid_handle(); } #endif - - torrent* find_torrent( - session_impl* ses - , aux::checker_impl* chk - , sha1_hash const& hash) - { - aux::piece_checker_data* d = chk->find_torrent(hash); - if (d != 0) return d->torrent_ptr.get(); - - boost::shared_ptr t = ses->find_torrent(hash).lock(); - if (t) return t.get(); - return 0; - } } #ifndef NDEBUG void torrent_handle::check_invariant() const - { - TORRENT_ASSERT((m_ses == 0 && m_chk == 0) || (m_ses != 0 && m_chk != 0)); - } + {} #endif + sha1_hash torrent_handle::info_hash() const + { + INVARIANT_CHECK; + const static sha1_hash empty; + TORRENT_FORWARD_RETURN(torrent_file().info_hash(), empty); + } + void torrent_handle::set_max_uploads(int max_uploads) const { INVARIANT_CHECK; @@ -241,6 +215,12 @@ namespace libtorrent TORRENT_FORWARD(move_storage(save_path)); } + void torrent_handle::rename_file(int index, fs::path const& new_name) const + { + INVARIANT_CHECK; + TORRENT_FORWARD(rename_file(index, new_name.string())); + } + void torrent_handle::add_extension( boost::function(torrent*, void*)> const& ext , void* userdata) @@ -279,12 +259,66 @@ namespace libtorrent TORRENT_FORWARD(pause()); } + void torrent_handle::save_resume_data() const + { + INVARIANT_CHECK; + TORRENT_FORWARD(save_resume_data()); + } + + void torrent_handle::force_recheck() const + { + INVARIANT_CHECK; + TORRENT_FORWARD(force_recheck()); + } + void torrent_handle::resume() const { INVARIANT_CHECK; TORRENT_FORWARD(resume()); } + bool torrent_handle::is_auto_managed() const + { + INVARIANT_CHECK; + TORRENT_FORWARD_RETURN(is_auto_managed(), true); + } + + void torrent_handle::auto_managed(bool m) const + { + INVARIANT_CHECK; + TORRENT_FORWARD(auto_managed(m)); + } + + int torrent_handle::queue_position() const + { + INVARIANT_CHECK; + TORRENT_FORWARD_RETURN(queue_position(), -1); + } + + void torrent_handle::queue_position_up() const + { + INVARIANT_CHECK; + TORRENT_FORWARD(set_queue_position(t->queue_position() - 1)); + } + + void torrent_handle::queue_position_down() const + { + INVARIANT_CHECK; + TORRENT_FORWARD(set_queue_position(t->queue_position() + 1)); + } + + void torrent_handle::queue_position_top() const + { + INVARIANT_CHECK; + TORRENT_FORWARD(set_queue_position(0)); + } + + void torrent_handle::queue_position_bottom() const + { + INVARIANT_CHECK; + TORRENT_FORWARD(set_queue_position((std::numeric_limits::max)())); + } + void torrent_handle::set_tracker_login(std::string const& name , std::string const& password) const { @@ -301,50 +335,19 @@ namespace libtorrent torrent_status torrent_handle::status() const { INVARIANT_CHECK; - - if (m_ses == 0) -#ifdef BOOST_NO_EXCEPTIONS - return torrent_status(); -#else - throw_invalid_handle(); -#endif - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - - aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash); - if (d != 0) - { - torrent_status st = d->torrent_ptr->status(); - - if (d->processing) - { - if (d->torrent_ptr->is_allocating()) - st.state = torrent_status::allocating; - else - st.state = torrent_status::checking_files; - } - else - st.state = torrent_status::queued_for_checking; - st.progress = d->progress; - st.paused = d->torrent_ptr->is_paused(); - return st; - } - - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (t) return t->status(); - -#ifndef BOOST_NO_EXCEPTIONS - throw_invalid_handle(); -#endif - return torrent_status(); + TORRENT_FORWARD_RETURN(status(), torrent_status()); } - void torrent_handle::set_sequenced_download_threshold(int threshold) const + void torrent_handle::set_sequential_download(bool sd) const { INVARIANT_CHECK; - TORRENT_FORWARD(set_sequenced_download_threshold(threshold)); + TORRENT_FORWARD(set_sequential_download(sd)); + } + + bool torrent_handle::is_sequential_download() const + { + INVARIANT_CHECK; + TORRENT_FORWARD_RETURN(is_sequential_download(), false); } std::string torrent_handle::name() const @@ -466,15 +469,16 @@ namespace libtorrent INVARIANT_CHECK; #ifdef BOOST_NO_EXCEPTIONS const static torrent_info empty; - if (m_ses == 0) return empty; -#else - if (m_ses == 0) throw_invalid_handle(); #endif - TORRENT_ASSERT(m_chk); - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - torrent* t = find_torrent(m_ses, m_chk, m_info_hash); - if (t == 0 || !t->valid_metadata()) + boost::shared_ptr t = m_torrent.lock(); + if (!t) +#ifdef BOOST_NO_EXCEPTIONS + return empty; +#else + throw_invalid_handle(); +#endif + session_impl::mutex_t::scoped_lock l(t->session().m_mutex); + if (!t->valid_metadata()) #ifdef BOOST_NO_EXCEPTIONS return empty; #else @@ -486,158 +490,15 @@ namespace libtorrent bool torrent_handle::is_valid() const { INVARIANT_CHECK; - if (m_ses == 0) return false; - TORRENT_ASSERT(m_chk); - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - torrent* t = find_torrent(m_ses, m_chk, m_info_hash); - return t != 0; + return !m_torrent.expired(); } entry torrent_handle::write_resume_data() const { INVARIANT_CHECK; - if (m_ses == 0) -#ifdef BOOST_NO_EXCEPTIONS - return entry(); -#else - throw_invalid_handle(); -#endif - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - - torrent* t = find_torrent(m_ses, m_chk, m_info_hash); - if (!t || !t->valid_metadata()) -#ifdef BOOST_NO_EXCEPTIONS - return entry(); -#else - throw_invalid_handle(); -#endif - - std::vector have_pieces = t->pieces(); - entry ret(entry::dictionary_t); - - ret["file-format"] = "libtorrent resume file"; - ret["file-version"] = 1; - - ret["allocation"] = t->filesystem().compact_allocation()?"compact":"full"; - - const sha1_hash& info_hash = t->torrent_file().info_hash(); - ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end()); - - // blocks per piece - int num_blocks_per_piece = - static_cast(t->torrent_file().piece_length()) / t->block_size(); - ret["blocks per piece"] = num_blocks_per_piece; - - // if this torrent is a seed, we won't have a piece picker - // and there will be no half-finished pieces. - if (!t->is_seed()) - { - const piece_picker& p = t->picker(); - - const std::vector& q - = p.get_download_queue(); - - // unfinished pieces - ret["unfinished"] = entry::list_type(); - entry::list_type& up = ret["unfinished"].list(); - - // info for each unfinished piece - for (std::vector::const_iterator i - = q.begin(); i != q.end(); ++i) - { - if (i->finished == 0) continue; - - entry piece_struct(entry::dictionary_t); - - // the unfinished piece's index - piece_struct["piece"] = i->index; - - have_pieces[i->index] = true; - - std::string bitmask; - const int num_bitmask_bytes - = (std::max)(num_blocks_per_piece / 8, 1); - - for (int j = 0; j < num_bitmask_bytes; ++j) - { - unsigned char v = 0; - int bits = (std::min)(num_blocks_per_piece - j*8, 8); - for (int k = 0; k < bits; ++k) - v |= (i->info[j*8+k].state == piece_picker::block_info::state_finished) - ? (1 << k) : 0; - bitmask.insert(bitmask.end(), v); - TORRENT_ASSERT(bits == 8 || j == num_bitmask_bytes - 1); - } - piece_struct["bitmask"] = bitmask; -/* - TORRENT_ASSERT(t->filesystem().slot_for(i->index) >= 0); - unsigned long adler - = t->filesystem().piece_crc( - t->filesystem().slot_for(i->index) - , t->block_size() - , i->info); - - piece_struct["adler32"] = adler; -*/ - // push the struct onto the unfinished-piece list - up.push_back(piece_struct); - } - } - - std::vector piece_index; - t->filesystem().export_piece_map(piece_index, have_pieces); - entry::list_type& slots = ret["slots"].list(); - std::copy(piece_index.begin(), piece_index.end(), std::back_inserter(slots)); - - // write local peers - - entry::list_type& peer_list = ret["peers"].list(); - entry::list_type& banned_peer_list = ret["banned_peers"].list(); - - policy& pol = t->get_policy(); - - int max_failcount = t->settings().max_failcount; - - for (policy::iterator i = pol.begin_peer() - , end(pol.end_peer()); i != end; ++i) - { - asio::error_code ec; - if (i->second.banned) - { - tcp::endpoint ip = i->second.ip; - entry peer(entry::dictionary_t); - peer["ip"] = ip.address().to_string(ec); - if (ec) continue; - peer["port"] = ip.port(); - banned_peer_list.push_back(peer); - continue; - } - // we cannot save remote connection - // since we don't know their listen port - // unless they gave us their listen port - // through the extension handshake - // so, if the peer is not connectable (i.e. we - // don't know its listen port) or if it has - // been banned, don't save it. - if (i->second.type == policy::peer::not_connectable) continue; - - // don't save peers that doesn't work - if (i->second.failcount >= max_failcount) continue; - - tcp::endpoint ip = i->second.ip; - entry peer(entry::dictionary_t); - peer["ip"] = ip.address().to_string(ec); - if (ec) continue; - peer["port"] = ip.port(); - peer_list.push_back(peer); - } - + TORRENT_FORWARD(write_resume_data(ret)); t->filesystem().write_resume_data(ret); return ret; @@ -654,35 +515,15 @@ namespace libtorrent { INVARIANT_CHECK; - if (m_ses == 0) + boost::shared_ptr t = m_torrent.lock(); + if (!t) #ifdef BOOST_NO_EXCEPTIONS return; #else throw_invalid_handle(); #endif - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); + session_impl::mutex_t::scoped_lock l(t->session().m_mutex); - if (!t) - { - // the torrent is being checked. Add the peer to its - // peer list. The entries in there will be connected - // once the checking is complete. - mutex::scoped_lock l2(m_chk->m_mutex); - - aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash); - if (d == 0) -#ifdef BOOST_NO_EXCEPTIONS - return; -#else - throw_invalid_handle(); -#endif - d->peers.push_back(adr); - return; - } - peer_id id; std::fill(id.begin(), id.end(), 0); t->get_policy().peer_from_tracker(adr, id, source, 0); @@ -731,6 +572,12 @@ namespace libtorrent } #endif + void torrent_handle::get_full_peer_list(std::vector& v) const + { + INVARIANT_CHECK; + TORRENT_FORWARD(get_full_peer_list(v)); + } + void torrent_handle::get_peer_info(std::vector& v) const { INVARIANT_CHECK; diff --git a/libtorrent/src/torrent_info.cpp b/libtorrent/src/torrent_info.cpp index c3040f80e..c6c222fa0 100755 --- a/libtorrent/src/torrent_info.cpp +++ b/libtorrent/src/torrent_info.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2003, Arvid Norberg +Copyright (c) 2003-2008, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -46,7 +46,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include -#include +#include #include #ifdef _MSC_VER @@ -57,8 +57,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/bencode.hpp" #include "libtorrent/hasher.hpp" #include "libtorrent/entry.hpp" +#include "libtorrent/file.hpp" -namespace pt = boost::posix_time; namespace gr = boost::gregorian; using namespace libtorrent; @@ -153,17 +153,16 @@ namespace // save the original encoding and replace the // commonly used path with the correctly // encoded string - if (!valid_encoding) - { - target.orig_path.reset(new fs::path(target.path)); - target.path = tmp_path; - } + if (!valid_encoding) target.path = tmp_path; } - void extract_single_file(const entry& dict, file_entry& target + bool extract_single_file(lazy_entry const& dict, file_entry& target , std::string const& root_dir) { - target.size = dict["length"].integer(); + lazy_entry const* length = dict.dict_find("length"); + if (length == 0 || length->type() != lazy_entry::int_t) + return false; + target.size = length->int_value(); target.path = root_dir; target.file_base = 0; @@ -171,74 +170,113 @@ namespace // because if it exists, it is more // likely to be correctly encoded - const entry::list_type* list = 0; - if (entry const* p = dict.find_key("path.utf-8")) - { - list = &p->list(); - } - else - { - list = &dict["path"].list(); - } + lazy_entry const* p = dict.dict_find("path.utf-8"); + if (p == 0 || p->type() != lazy_entry::list_t) + p = dict.dict_find("path"); + if (p == 0 || p->type() != lazy_entry::list_t) + return false; - for (entry::list_type::const_iterator i = list->begin(); - i != list->end(); ++i) + for (int i = 0, end(p->list_size()); i < end; ++i) { - if (i->string() != "..") - target.path /= i->string(); + if (p->list_at(i)->type() != lazy_entry::string_t) + return false; + std::string path_element = p->list_at(i)->string_value(); + if (path_element != "..") + target.path /= path_element; } verify_encoding(target); - if (target.path.is_complete()) throw std::runtime_error("torrent contains " - "a file with an absolute path: '" - + target.path.native_file_string() + "'"); + if (target.path.is_complete()) + return false; + return true; } - void extract_files(const entry::list_type& list, std::vector& target + bool extract_files(lazy_entry const& list, file_storage& target , std::string const& root_dir) { - size_type offset = 0; - for (entry::list_type::const_iterator i = list.begin(); i != list.end(); ++i) + if (list.type() != lazy_entry::list_t) return false; + for (int i = 0, end(list.list_size()); i < end; ++i) { - target.push_back(file_entry()); - extract_single_file(*i, target.back(), root_dir); - target.back().offset = offset; - offset += target.back().size; + file_entry e; + if (!extract_single_file(*list.list_at(i), e, root_dir)) + return false; + target.add_file(e); } + return true; } -/* - void remove_dir(fs::path& p) - { - TORRENT_ASSERT(p.begin() != p.end()); - path tmp; - for (path::iterator i = boost::next(p.begin()); i != p.end(); ++i) - tmp /= *i; - p = tmp; - } -*/ } namespace libtorrent { + int load_file(fs::path const& filename, std::vector& v) + { + file f; + if (!f.open(filename, file::in)) return -1; + f.seek(0, file::end); + size_type s = f.tell(); + if (s > 5000000) return -2; + v.resize(s); + f.seek(0); + size_type read = f.read(&v[0], s); + if (read != s) return -3; + return 0; + } + // standard constructor that parses a torrent file - torrent_info::torrent_info(const entry& torrent_file) - : m_num_pieces(0) - , m_creation_date(pt::ptime(pt::not_a_date_time)) + torrent_info::torrent_info(entry const& torrent_file) + : m_creation_date(pt::ptime(pt::not_a_date_time)) , m_multifile(false) , m_private(false) - , m_extra_info(entry::dictionary_t) -#ifndef NDEBUG - , m_half_metadata(false) -#endif + , m_info_section_size(0) + , m_piece_hashes(0) { - try - { - read_torrent_info(torrent_file); - } - catch(type_error&) - { + std::vector tmp; + std::back_insert_iterator > out(tmp); + bencode(out, torrent_file); + + lazy_entry e; + lazy_bdecode(&tmp[0], &tmp[0] + tmp.size(), e); + std::string error; +#ifndef BOOST_NO_EXCEPTIONS + if (!parse_torrent_file(e, error)) throw invalid_torrent_file(); - } +#else + parse_torrent_file(e, error); +#endif + } + + torrent_info::torrent_info(lazy_entry const& torrent_file) + : m_creation_date(pt::ptime(pt::not_a_date_time)) + , m_multifile(false) + , m_private(false) + , m_info_section_size(0) + , m_piece_hashes(0) + { + std::string error; +#ifndef BOOST_NO_EXCEPTIONS + if (!parse_torrent_file(torrent_file, error)) + throw invalid_torrent_file(); +#else + parse_torrent_file(torrent_file, error); +#endif + } + + torrent_info::torrent_info(char const* buffer, int size) + : m_creation_date(pt::ptime(pt::not_a_date_time)) + , m_multifile(false) + , m_private(false) + , m_info_section_size(0) + , m_piece_hashes(0) + { + std::string error; + lazy_entry e; + lazy_bdecode(buffer, buffer + size, e); +#ifndef BOOST_NO_EXCEPTIONS + if (!parse_torrent_file(e, error)) + throw invalid_torrent_file(); +#else + parse_torrent_file(e, error); +#endif } // constructor used for creating new torrents @@ -246,35 +284,32 @@ namespace libtorrent // just the necessary to use it with piece manager // used for torrents with no metadata torrent_info::torrent_info(sha1_hash const& info_hash) - : m_piece_length(0) - , m_total_size(0) - , m_num_pieces(0) - , m_info_hash(info_hash) - , m_name() + : m_info_hash(info_hash) , m_creation_date(pt::second_clock::universal_time()) , m_multifile(false) , m_private(false) - , m_extra_info(entry::dictionary_t) -#ifndef NDEBUG - , m_half_metadata(false) -#endif - { - } + , m_info_section_size(0) + , m_piece_hashes(0) + {} - torrent_info::torrent_info() - : m_piece_length(0) - , m_total_size(0) - , m_num_pieces(0) - , m_info_hash(0) - , m_name() - , m_creation_date(pt::second_clock::universal_time()) + torrent_info::torrent_info(fs::path const& filename) + : m_creation_date(pt::ptime(pt::not_a_date_time)) , m_multifile(false) , m_private(false) - , m_extra_info(entry::dictionary_t) -#ifndef NDEBUG - , m_half_metadata(false) -#endif { + std::vector buf; + int ret = load_file(filename, buf); + if (ret < 0) return; + + lazy_entry e; + lazy_bdecode(&buf[0], &buf[0] + buf.size(), e); + std::string error; +#ifndef BOOST_NO_EXCEPTIONS + if (!parse_torrent_file(e, error)) + throw invalid_torrent_file(); +#else + parse_torrent_file(e, error); +#endif } torrent_info::~torrent_info() @@ -285,188 +320,164 @@ namespace libtorrent using std::swap; m_urls.swap(ti.m_urls); m_url_seeds.swap(ti.m_url_seeds); - swap(m_piece_length, ti.m_piece_length); - m_piece_hash.swap(ti.m_piece_hash); m_files.swap(ti.m_files); m_nodes.swap(ti.m_nodes); - swap(m_num_pieces, ti.m_num_pieces); swap(m_info_hash, ti.m_info_hash); - m_name.swap(ti.m_name); swap(m_creation_date, ti.m_creation_date); m_comment.swap(ti.m_comment); m_created_by.swap(ti.m_created_by); swap(m_multifile, ti.m_multifile); swap(m_private, ti.m_private); - m_extra_info.swap(ti.m_extra_info); -#ifndef NDEBUG - swap(m_half_metadata, ti.m_half_metadata); -#endif + swap(m_info_section, ti.m_info_section); + swap(m_info_section_size, ti.m_info_section_size); + swap(m_piece_hashes, ti.m_piece_hashes); + swap(m_info_dict, ti.m_info_dict); } - void torrent_info::set_piece_size(int size) + bool torrent_info::parse_info_section(lazy_entry const& info, std::string& error) { - // make sure the size is an even power of 2 -#ifndef NDEBUG - for (int i = 0; i < 32; ++i) + if (info.type() != lazy_entry::dict_t) { - if (size & (1 << i)) - { - TORRENT_ASSERT((size & ~(1 << i)) == 0); - break; - } + error = "'info' entry is not a dictionary"; + return false; } -#endif - TORRENT_ASSERT(!m_half_metadata); - m_piece_length = size; - m_num_pieces = static_cast( - (m_total_size + m_piece_length - 1) / m_piece_length); - int old_num_pieces = static_cast(m_piece_hash.size()); - - m_piece_hash.resize(m_num_pieces); - for (int i = old_num_pieces; i < m_num_pieces; ++i) - { - m_piece_hash[i].clear(); - } - } - - void torrent_info::parse_info_section(entry const& info) - { - // encode the info-field in order to calculate it's sha1-hash - std::vector buf; - bencode(std::back_inserter(buf), info); + // hash the info-field to calculate info-hash hasher h; - h.update(&buf[0], (int)buf.size()); + std::pair section = info.data_section(); + h.update(section.first, section.second); m_info_hash = h.final(); + // copy the info section + m_info_section_size = section.second; + m_info_section.reset(new char[m_info_section_size]); + memcpy(m_info_section.get(), section.first, m_info_section_size); + TORRENT_ASSERT(section.first[0] == 'd'); + TORRENT_ASSERT(section.first[m_info_section_size-1] == 'e'); + // extract piece length - m_piece_length = int(info["piece length"].integer()); - if (m_piece_length <= 0) throw std::runtime_error("invalid torrent. piece length <= 0"); + int piece_length = info.dict_find_int_value("piece length", -1); + if (piece_length <= 0) + { + error = "invalid or missing 'piece length' entry in torrent file"; + return false; + } + m_files.set_piece_length(piece_length); // extract file name (or the directory name if it's a multifile libtorrent) - if (entry const* e = info.find_key("name.utf-8")) - { m_name = e->string(); } - else - { m_name = info["name"].string(); } - - fs::path tmp = m_name; - if (tmp.is_complete()) - { - m_name = tmp.leaf(); - } - else if (tmp.has_branch_path()) - { - fs::path p; - for (fs::path::iterator i = tmp.begin() - , end(tmp.end()); i != end; ++i) - { - if (*i == "." || *i == "..") continue; - p /= *i; - } - m_name = p.string(); - } - if (m_name == ".." || m_name == ".") - throw std::runtime_error("invalid 'name' of torrent (possible exploit attempt)"); + std::string name = info.dict_find_string_value("name.utf-8"); + if (name.empty()) name = info.dict_find_string_value("name"); + if (name.empty()) + { + error = "missing name in torrent file"; + return false; + } + + fs::path tmp = name; + if (tmp.is_complete()) + { + name = tmp.leaf(); + } + else if (tmp.has_branch_path()) + { + fs::path p; + for (fs::path::iterator i = tmp.begin() + , end(tmp.end()); i != end; ++i) + { + if (*i == "." || *i == "..") continue; + p /= *i; + } + name = p.string(); + } + if (name == ".." || name == ".") + { + error = "invalid 'name' of torrent (possible exploit attempt)"; + return false; + } // extract file list - entry const* i = info.find_key("files"); + lazy_entry const* i = info.dict_find_list("files"); if (i == 0) { // if there's no list of files, there has to be a length // field. file_entry e; - e.path = m_name; + e.path = name; e.offset = 0; - e.size = info["length"].integer(); - m_files.push_back(e); + e.size = info.dict_find_int_value("length", -1); + if (e.size < 0) + { + error = "invalid length of torrent"; + return false; + } + m_files.add_file(e); + m_multifile = false; } else { - extract_files(i->list(), m_files, m_name); + if (!extract_files(*i, m_files, name)) + { + error = "failed to parse files from torrent file"; + return false; + } m_multifile = true; } - - // calculate total size of all pieces - m_total_size = 0; - for (std::vector::iterator i = m_files.begin(); i != m_files.end(); ++i) - m_total_size += i->size; + m_files.set_name(name); // extract sha-1 hashes for all pieces // we want this division to round upwards, that's why we have the // extra addition - m_num_pieces = static_cast((m_total_size + m_piece_length - 1) / m_piece_length); - m_piece_hash.resize(m_num_pieces); - const std::string& hash_string = info["pieces"].string(); + m_files.set_num_pieces(int((m_files.total_size() + m_files.piece_length() - 1) + / m_files.piece_length())); - if ((int)hash_string.length() != m_num_pieces * 20) - throw invalid_torrent_file(); - - for (int i = 0; i < m_num_pieces; ++i) - std::copy( - hash_string.begin() + i*20 - , hash_string.begin() + (i+1)*20 - , m_piece_hash[i].begin()); - - for (entry::dictionary_type::const_iterator i = info.dict().begin() - , end(info.dict().end()); i != end; ++i) + lazy_entry const* pieces = info.dict_find("pieces"); + if (pieces == 0 || pieces->type() != lazy_entry::string_t) { - if (i->first == "pieces" - || i->first == "piece length" - || i->first == "length") - continue; - m_extra_info[i->first] = i->second; + error = "invalid or missing 'pieces' entry in torrent file"; + return false; + } + + if (pieces->string_length() != m_files.num_pieces() * 20) + { + error = "incorrect number of piece hashes in torrent file"; + return false; } - if (entry const* priv = info.find_key("private")) - { - if (priv->type() != entry::int_t - || priv->integer() != 0) - { - // this key exists and it's not 0. - // consider the torrent private - m_private = true; - } - } + m_piece_hashes = m_info_section.get() + (pieces->string_ptr() - section.first); + TORRENT_ASSERT(m_piece_hashes >= m_info_section.get()); + TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size); -#ifndef NDEBUG - std::vector info_section_buf; - entry gen_info_section = create_info_metadata(); - bencode(std::back_inserter(info_section_buf), gen_info_section); - TORRENT_ASSERT(hasher(&info_section_buf[0], info_section_buf.size()).final() - == m_info_hash); -#endif + m_private = info.dict_find_int_value("private", 0); + return true; } - // extracts information from a libtorrent file and fills in the structures in - // the torrent object - void torrent_info::read_torrent_info(const entry& torrent_file) + bool torrent_info::parse_torrent_file(lazy_entry const& torrent_file, std::string& error) { - // extract the url of the tracker - entry const* i = torrent_file.find_key("announce-list"); - if (i && i->type() == entry::list_t) + if (torrent_file.type() != lazy_entry::dict_t) { - const entry::list_type& l = i->list(); - for (entry::list_type::const_iterator j = l.begin(); j != l.end(); ++j) + error = "torrent file is not a dictionary"; + return false; + } + + // extract the url of the tracker + lazy_entry const* i = torrent_file.dict_find_list("announce-list"); + if (i) + { + m_urls.reserve(i->list_size()); + for (int j = 0, end(i->list_size()); j < end; ++j) { - if (j->type() != entry::list_t) continue; - const entry::list_type& ll = j->list(); - for (entry::list_type::const_iterator k = ll.begin(); k != ll.end(); ++k) + lazy_entry const* tier = i->list_at(j); + if (tier->type() != lazy_entry::list_t) continue; + for (int k = 0, end(tier->list_size()); k < end; ++k) { - if (k->type() != entry::string_t) continue; - announce_entry e(k->string()); - e.tier = (int)std::distance(l.begin(), j); + announce_entry e(tier->list_string_value_at(k)); + if (e.url.empty()) continue; + e.tier = j; m_urls.push_back(e); } } - if (m_urls.size() == 0) - { - // the announce-list is empty - // fall back to look for announce - m_urls.push_back(announce_entry( - torrent_file["announce"].string())); - } // shuffle each tier std::vector::iterator start = m_urls.begin(); std::vector::iterator stop; @@ -482,69 +493,68 @@ namespace libtorrent } std::random_shuffle(start, stop); } - else if (entry const* i = torrent_file.find_key("announce")) + + + if (m_urls.empty()) { - m_urls.push_back(announce_entry(i->string())); + announce_entry e(torrent_file.dict_find_string_value("announce")); + if (!e.url.empty()) m_urls.push_back(e); } - if (entry const* i = torrent_file.find_key("nodes")) + lazy_entry const* nodes = torrent_file.dict_find_list("nodes"); + if (nodes) { - entry::list_type const& list = i->list(); - for (entry::list_type::const_iterator i(list.begin()) - , end(list.end()); i != end; ++i) + for (int i = 0, end(nodes->list_size()); i < end; ++i) { - if (i->type() != entry::list_t) continue; - entry::list_type const& l = i->list(); - entry::list_type::const_iterator iter = l.begin(); - if (l.size() < 1) continue; - std::string const& hostname = iter->string(); - ++iter; - int port = 6881; - if (l.end() != iter) port = int(iter->integer()); - m_nodes.push_back(std::make_pair(hostname, port)); + lazy_entry const* n = nodes->list_at(i); + if (n->type() != lazy_entry::list_t + || n->list_size() < 2 + || n->list_at(0)->type() != lazy_entry::string_t + || n->list_at(1)->type() != lazy_entry::int_t) + continue; + m_nodes.push_back(std::make_pair( + n->list_at(0)->string_value() + , int(n->list_at(1)->int_value()))); } } // extract creation date - try + size_type cd = torrent_file.dict_find_int_value("creation date", -1); + if (cd >= 0) { m_creation_date = pt::ptime(gr::date(1970, gr::Jan, 1)) - + pt::seconds(long(torrent_file["creation date"].integer())); + + pt::seconds(long(cd)); } - catch (type_error) {} // if there are any url-seeds, extract them - try + lazy_entry const* url_seeds = torrent_file.dict_find("url-list"); + if (url_seeds && url_seeds->type() == lazy_entry::string_t) { - entry const& url_seeds = torrent_file["url-list"]; - if (url_seeds.type() == entry::string_t) + m_url_seeds.push_back(url_seeds->string_value()); + } + else if (url_seeds && url_seeds->type() == lazy_entry::list_t) + { + for (int i = 0, end(url_seeds->list_size()); i < end; ++i) { - m_url_seeds.push_back(url_seeds.string()); - } - else if (url_seeds.type() == entry::list_t) - { - entry::list_type const& l = url_seeds.list(); - for (entry::list_type::const_iterator i = l.begin(); - i != l.end(); ++i) - { - m_url_seeds.push_back(i->string()); - } + lazy_entry const* url = url_seeds->list_at(i); + if (url->type() != lazy_entry::string_t) continue; + m_url_seeds.push_back(url->string_value()); } } - catch (type_error&) {} - // extract comment - if (entry const* e = torrent_file.find_key("comment.utf-8")) - { m_comment = e->string(); } - else if (entry const* e = torrent_file.find_key("comment")) - { m_comment = e->string(); } + m_comment = torrent_file.dict_find_string_value("comment.utf-8"); + if (m_comment.empty()) m_comment = torrent_file.dict_find_string_value("comment"); - if (entry const* e = torrent_file.find_key("created by.utf-8")) - { m_created_by = e->string(); } - else if (entry const* e = torrent_file.find_key("created by")) - { m_created_by = e->string(); } + m_created_by = torrent_file.dict_find_string_value("created by.utf-8"); + if (m_created_by.empty()) m_created_by = torrent_file.dict_find_string_value("created by"); - parse_info_section(torrent_file["info"]); + lazy_entry const* info = torrent_file.dict_find_dict("info"); + if (info == 0) + { + error = "missing or invalid 'info' section in torrent file"; + return false; + } + return parse_info_section(*info, error); } boost::optional @@ -568,234 +578,6 @@ namespace libtorrent , bind(&announce_entry::tier, _1), bind(&announce_entry::tier, _2))); } - void torrent_info::add_file(fs::path file, size_type size) - { -// TORRENT_ASSERT(file.begin() != file.end()); - - if (!file.has_branch_path()) - { - // you have already added at least one file with a - // path to the file (branch_path), which means that - // all the other files need to be in the same top - // directory as the first file. - TORRENT_ASSERT(m_files.empty()); - TORRENT_ASSERT(!m_multifile); - m_name = file.string(); - } - else - { -#ifndef NDEBUG - if (!m_files.empty()) - TORRENT_ASSERT(m_name == *file.begin()); -#endif - m_multifile = true; - m_name = *file.begin(); - } - - file_entry e; - e.path = file; - e.size = size; - e.offset = m_files.empty() ? 0 : m_files.back().offset - + m_files.back().size; - m_files.push_back(e); - - m_total_size += size; - - if (m_piece_length == 0) - m_piece_length = 256 * 1024; - - m_num_pieces = static_cast( - (m_total_size + m_piece_length - 1) / m_piece_length); - int old_num_pieces = static_cast(m_piece_hash.size()); - - m_piece_hash.resize(m_num_pieces); - if (m_num_pieces > old_num_pieces) - std::for_each(m_piece_hash.begin() + old_num_pieces - , m_piece_hash.end(), boost::bind(&sha1_hash::clear, _1)); - } - - void torrent_info::add_url_seed(std::string const& url) - { - m_url_seeds.push_back(url); - } - - void torrent_info::set_comment(char const* str) - { - m_comment = str; - } - - void torrent_info::set_creator(char const* str) - { - m_created_by = str; - } - - entry torrent_info::create_info_metadata() const - { - // you have to add files to the torrent first - TORRENT_ASSERT(!m_files.empty()); - - entry info(m_extra_info); - - if (!info.find_key("name")) - info["name"] = m_name; - - if (m_private) info["private"] = 1; - - if (!m_multifile) - { - info["length"] = m_files.front().size; - } - else - { - if (!info.find_key("files")) - { - entry& files = info["files"]; - - for (std::vector::const_iterator i = m_files.begin(); - i != m_files.end(); ++i) - { - files.list().push_back(entry()); - entry& file_e = files.list().back(); - file_e["length"] = i->size; - entry& path_e = file_e["path"]; - - fs::path const* file_path; - if (i->orig_path) file_path = &(*i->orig_path); - else file_path = &i->path; - TORRENT_ASSERT(file_path->has_branch_path()); - TORRENT_ASSERT(*file_path->begin() == m_name); - - for (fs::path::iterator j = boost::next(file_path->begin()); - j != file_path->end(); ++j) - { - path_e.list().push_back(entry(*j)); - } - } - } - } - - info["piece length"] = piece_length(); - entry& pieces = info["pieces"]; - - std::string& p = pieces.string(); - - for (std::vector::const_iterator i = m_piece_hash.begin(); - i != m_piece_hash.end(); ++i) - { - p.append((char*)i->begin(), (char*)i->end()); - } - - return info; - } - - entry torrent_info::create_torrent() const - { - TORRENT_ASSERT(m_piece_length > 0); - - if (m_files.empty()) - { - // TODO: throw something here - // throw - return entry(); - } - - entry dict; - - if (!m_urls.empty()) - dict["announce"] = m_urls.front().url; - - if (!m_nodes.empty()) - { - entry& nodes = dict["nodes"]; - entry::list_type& nodes_list = nodes.list(); - for (nodes_t::const_iterator i = m_nodes.begin() - , end(m_nodes.end()); i != end; ++i) - { - entry::list_type node; - node.push_back(entry(i->first)); - node.push_back(entry(i->second)); - nodes_list.push_back(entry(node)); - } - } - - if (m_urls.size() > 1) - { - entry trackers(entry::list_t); - entry tier(entry::list_t); - int current_tier = m_urls.front().tier; - for (std::vector::const_iterator i = m_urls.begin(); - i != m_urls.end(); ++i) - { - if (i->tier != current_tier) - { - current_tier = i->tier; - trackers.list().push_back(tier); - tier.list().clear(); - } - tier.list().push_back(entry(i->url)); - } - trackers.list().push_back(tier); - dict["announce-list"] = trackers; - } - - if (!m_comment.empty()) - dict["comment"] = m_comment; - - dict["creation date"] = - (m_creation_date - pt::ptime(gr::date(1970, gr::Jan, 1))).total_seconds(); - - if (!m_created_by.empty()) - dict["created by"] = m_created_by; - - if (!m_url_seeds.empty()) - { - if (m_url_seeds.size() == 1) - { - dict["url-list"] = m_url_seeds.front(); - } - else - { - entry& list = dict["url-list"]; - for (std::vector::const_iterator i - = m_url_seeds.begin(); i != m_url_seeds.end(); ++i) - { - list.list().push_back(entry(*i)); - } - } - } - - dict["info"] = create_info_metadata(); - - entry const& info_section = dict["info"]; - std::vector buf; - bencode(std::back_inserter(buf), info_section); - m_info_hash = hasher(&buf[0], buf.size()).final(); - - return dict; - } - - void torrent_info::set_hash(int index, const sha1_hash& h) - { - TORRENT_ASSERT(index >= 0); - TORRENT_ASSERT(index < (int)m_piece_hash.size()); - m_piece_hash[index] = h; - } - - void torrent_info::convert_file_names() - { - TORRENT_ASSERT(false); - } - - void torrent_info::seed_free() - { - std::vector().swap(m_url_seeds); - nodes_t().swap(m_nodes); - std::vector().swap(m_piece_hash); -#ifndef NDEBUG - m_half_metadata = true; -#endif - } - // ------- start deprecation ------- void torrent_info::print(std::ostream& os) const @@ -814,126 +596,11 @@ namespace libtorrent os << "number of pieces: " << num_pieces() << "\n"; os << "piece length: " << piece_length() << "\n"; os << "files:\n"; - for (file_iterator i = begin_files(); i != end_files(); ++i) + for (file_storage::iterator i = m_files.begin(); i != m_files.end(); ++i) os << " " << std::setw(11) << i->size << " " << i->path.string() << "\n"; } // ------- end deprecation ------- - int torrent_info::piece_size(int index) const - { - TORRENT_ASSERT(index >= 0 && index < num_pieces()); - if (index == num_pieces()-1) - { - size_type size = total_size() - - size_type(num_pieces() - 1) * piece_length(); - TORRENT_ASSERT(size > 0); - TORRENT_ASSERT(size <= piece_length()); - return int(size); - } - else - return piece_length(); - } - - void torrent_info::add_node(std::pair const& node) - { - m_nodes.push_back(node); - } - - bool torrent_info::remap_files(std::vector const& map) - { - size_type offset = 0; - m_remapped_files.resize(map.size()); - - for (int i = 0; i < int(map.size()); ++i) - { - file_entry& fe = m_remapped_files[i]; - fe.path = map[i].path; - fe.offset = offset; - fe.size = map[i].size; - fe.file_base = map[i].file_base; - fe.orig_path.reset(); - offset += fe.size; - } - if (offset != total_size()) - { - m_remapped_files.clear(); - return false; - } - -#ifndef NDEBUG - std::vector map2(m_remapped_files); - std::sort(map2.begin(), map2.end() - , bind(&file_entry::file_base, _1) < bind(&file_entry::file_base, _2)); - std::stable_sort(map2.begin(), map2.end() - , bind(&file_entry::path, _1) < bind(&file_entry::path, _2)); - fs::path last_path; - size_type last_end = 0; - for (std::vector::iterator i = map2.begin(), end(map2.end()); - i != end; ++i) - { - if (last_path == i->path) - { - assert(last_end <= i->file_base); - } - last_end = i->file_base + i->size; - last_path = i->path; - } -#endif - - return true; - } - - std::vector torrent_info::map_block(int piece, size_type offset - , int size_, bool storage) const - { - TORRENT_ASSERT(num_files() > 0); - std::vector ret; - - size_type start = piece * (size_type)m_piece_length + offset; - size_type size = size_; - TORRENT_ASSERT(start + size <= m_total_size); - - // find the file iterator and file offset - // TODO: make a vector that can map piece -> file index in O(1) - size_type file_offset = start; - std::vector::const_iterator file_iter; - - int counter = 0; - for (file_iter = begin_files(storage);; ++counter, ++file_iter) - { - TORRENT_ASSERT(file_iter != end_files(storage)); - if (file_offset < file_iter->size) - { - file_slice f; - f.file_index = counter; - f.offset = file_offset + file_iter->file_base; - f.size = (std::min)(file_iter->size - file_offset, (size_type)size); - size -= f.size; - file_offset += f.size; - ret.push_back(f); - } - - TORRENT_ASSERT(size >= 0); - if (size <= 0) break; - - file_offset -= file_iter->size; - } - return ret; - } - - peer_request torrent_info::map_file(int file_index, size_type file_offset - , int size, bool storage) const - { - TORRENT_ASSERT(file_index < num_files(storage)); - TORRENT_ASSERT(file_index >= 0); - size_type offset = file_offset + file_at(file_index, storage).offset; - - peer_request ret; - ret.piece = int(offset / piece_length()); - ret.start = int(offset - ret.piece * piece_length()); - ret.length = size; - return ret; - } - } + diff --git a/libtorrent/src/tracker_manager.cpp b/libtorrent/src/tracker_manager.cpp index b389c12ac..6a0b28d60 100755 --- a/libtorrent/src/tracker_manager.cpp +++ b/libtorrent/src/tracker_manager.cpp @@ -38,8 +38,6 @@ POSSIBILITY OF SUCH DAMAGE. #include #include -#include "zlib.h" - #include #include "libtorrent/tracker_manager.hpp" @@ -63,237 +61,14 @@ namespace http_buffer_size = 2048 }; - - enum - { - FTEXT = 0x01, - FHCRC = 0x02, - FEXTRA = 0x04, - FNAME = 0x08, - FCOMMENT = 0x10, - FRESERVED = 0xe0, - - GZIP_MAGIC0 = 0x1f, - GZIP_MAGIC1 = 0x8b - }; - } namespace libtorrent { - // returns -1 if gzip header is invalid or the header size in bytes - int gzip_header(const char* buf, int size) - { - TORRENT_ASSERT(buf != 0); - TORRENT_ASSERT(size > 0); - - const unsigned char* buffer = reinterpret_cast(buf); - const int total_size = size; - - // The zip header cannot be shorter than 10 bytes - if (size < 10) return -1; - - // check the magic header of gzip - if ((buffer[0] != GZIP_MAGIC0) || (buffer[1] != GZIP_MAGIC1)) return -1; - - int method = buffer[2]; - int flags = buffer[3]; - - // check for reserved flag and make sure it's compressed with the correct metod - if (method != Z_DEFLATED || (flags & FRESERVED) != 0) return -1; - - // skip time, xflags, OS code - size -= 10; - buffer += 10; - - if (flags & FEXTRA) - { - int extra_len; - - if (size < 2) return -1; - - extra_len = (buffer[1] << 8) | buffer[0]; - - if (size < (extra_len+2)) return -1; - size -= (extra_len + 2); - buffer += (extra_len + 2); - } - - if (flags & FNAME) - { - while (size && *buffer) - { - --size; - ++buffer; - } - if (!size || *buffer) return -1; - - --size; - ++buffer; - } - - if (flags & FCOMMENT) - { - while (size && *buffer) - { - --size; - ++buffer; - } - if (!size || *buffer) return -1; - - --size; - ++buffer; - } - - if (flags & FHCRC) - { - if (size < 2) return -1; - - size -= 2; - buffer += 2; - } - - return total_size - size; - } - - bool inflate_gzip( - std::vector& buffer - , tracker_request const& req - , request_callback* requester - , int maximum_tracker_response_length) - { - TORRENT_ASSERT(maximum_tracker_response_length > 0); - - int header_len = gzip_header(&buffer[0], (int)buffer.size()); - if (header_len < 0) - { - requester->tracker_request_error(req, 200, "invalid gzip header in tracker response"); - return true; - } - - // start off wth one kilobyte and grow - // if needed - std::vector inflate_buffer(1024); - - // initialize the zlib-stream - z_stream str; - - // subtract 8 from the end of the buffer since that's CRC32 and input size - // and those belong to the gzip file - str.avail_in = (int)buffer.size() - header_len - 8; - str.next_in = reinterpret_cast(&buffer[header_len]); - str.next_out = reinterpret_cast(&inflate_buffer[0]); - str.avail_out = (int)inflate_buffer.size(); - str.zalloc = Z_NULL; - str.zfree = Z_NULL; - str.opaque = 0; - // -15 is really important. It will make inflate() not look for a zlib header - // and just deflate the buffer - if (inflateInit2(&str, -15) != Z_OK) - { - requester->tracker_request_error(req, 200, "gzip out of memory"); - return true; - } - - // inflate and grow inflate_buffer as needed - int ret = inflate(&str, Z_SYNC_FLUSH); - while (ret == Z_OK) - { - if (str.avail_out == 0) - { - if (inflate_buffer.size() >= (unsigned)maximum_tracker_response_length) - { - inflateEnd(&str); - requester->tracker_request_error(req, 200 - , "tracker response too large"); - return true; - } - int new_size = (int)inflate_buffer.size() * 2; - if (new_size > maximum_tracker_response_length) new_size = maximum_tracker_response_length; - int old_size = (int)inflate_buffer.size(); - - inflate_buffer.resize(new_size); - str.next_out = reinterpret_cast(&inflate_buffer[old_size]); - str.avail_out = new_size - old_size; - } - - ret = inflate(&str, Z_SYNC_FLUSH); - } - - inflate_buffer.resize(inflate_buffer.size() - str.avail_out); - inflateEnd(&str); - - if (ret != Z_STREAM_END) - { - requester->tracker_request_error(req, 200, "gzip error"); - return true; - } - - // commit the resulting buffer - std::swap(buffer, inflate_buffer); - return false; - } - - std::string base64encode(const std::string& s) - { - static const char base64_table[] = - { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '/' - }; - - unsigned char inbuf[3]; - unsigned char outbuf[4]; - - std::string ret; - for (std::string::const_iterator i = s.begin(); i != s.end();) - { - // available input is 1,2 or 3 bytes - // since we read 3 bytes at a time at most - int available_input = (std::min)(3, (int)std::distance(i, s.end())); - - // clear input buffer - std::fill(inbuf, inbuf+3, 0); - - // read a chunk of input into inbuf - for (int j = 0; j < available_input; ++j) - { - inbuf[j] = *i; - ++i; - } - - // encode inbuf to outbuf - outbuf[0] = (inbuf[0] & 0xfc) >> 2; - outbuf[1] = ((inbuf[0] & 0x03) << 4) | ((inbuf [1] & 0xf0) >> 4); - outbuf[2] = ((inbuf[1] & 0x0f) << 2) | ((inbuf [2] & 0xc0) >> 6); - outbuf[3] = inbuf[2] & 0x3f; - - // write output - for (int j = 0; j < available_input+1; ++j) - { - ret += base64_table[outbuf[j]]; - } - - // write pad - for (int j = 0; j < 3 - available_input; ++j) - { - ret += '='; - } - } - return ret; - } - - timeout_handler::timeout_handler(asio::strand& str) - : m_strand(str) - , m_start_time(time_now()) + timeout_handler::timeout_handler(io_service& ios) + : m_start_time(time_now()) , m_read_time(time_now()) - , m_timeout(str.io_service()) + , m_timeout(ios) , m_completion_timeout(0) , m_read_timeout(0) , m_abort(false) @@ -309,9 +84,10 @@ namespace libtorrent int timeout = (std::min)( m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout)); - m_timeout.expires_at(m_read_time + seconds(timeout)); - m_timeout.async_wait(m_strand.wrap(bind( - &timeout_handler::timeout_callback, self(), _1))); + error_code ec; + m_timeout.expires_at(m_read_time + seconds(timeout), ec); + m_timeout.async_wait(bind( + &timeout_handler::timeout_callback, self(), _1)); } void timeout_handler::restart_read_timeout() @@ -323,10 +99,11 @@ namespace libtorrent { m_abort = true; m_completion_timeout = 0; - m_timeout.cancel(); + error_code ec; + m_timeout.cancel(ec); } - void timeout_handler::timeout_callback(asio::error_code const& error) try + void timeout_handler::timeout_callback(error_code const& error) { if (error) return; if (m_completion_timeout == 0) return; @@ -348,22 +125,19 @@ namespace libtorrent int timeout = (std::min)( m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout)); - m_timeout.expires_at(m_read_time + seconds(timeout)); - m_timeout.async_wait(m_strand.wrap( - bind(&timeout_handler::timeout_callback, self(), _1))); - } - catch (std::exception&) - { - TORRENT_ASSERT(false); + error_code ec; + m_timeout.expires_at(m_read_time + seconds(timeout), ec); + m_timeout.async_wait( + bind(&timeout_handler::timeout_callback, self(), _1)); } tracker_connection::tracker_connection( tracker_manager& man , tracker_request const& req - , asio::strand& str + , io_service& ios , address bind_interface_ , boost::weak_ptr r) - : timeout_handler(str) + : timeout_handler(ios) , m_requester(r) , m_bind_interface(bind_interface_) , m_man(man) @@ -406,88 +180,8 @@ namespace libtorrent m_connections.erase(i); } - // returns protocol, auth, hostname, port, path - tuple - parse_url_components(std::string url) - { - std::string hostname; // hostname only - std::string auth; // user:pass - std::string protocol; // should be http - int port = 80; - - // PARSE URL - std::string::iterator start = url.begin(); - // remove white spaces in front of the url - while (start != url.end() && (*start == ' ' || *start == '\t')) - ++start; - std::string::iterator end - = std::find(url.begin(), url.end(), ':'); - protocol.assign(start, end); - - if (end == url.end()) throw std::runtime_error("invalid url '" + url + "'"); - ++end; - if (end == url.end()) throw std::runtime_error("invalid url '" + url + "'"); - if (*end != '/') throw std::runtime_error("invalid url '" + url + "'"); - ++end; - if (end == url.end()) throw std::runtime_error("invalid url '" + url + "'"); - if (*end != '/') throw std::runtime_error("invalid url '" + url + "'"); - ++end; - start = end; - - std::string::iterator at = std::find(start, url.end(), '@'); - std::string::iterator colon = std::find(start, url.end(), ':'); - end = std::find(start, url.end(), '/'); - - if (at != url.end() - && colon != url.end() - && colon < at - && at < end) - { - auth.assign(start, at); - start = at; - ++start; - } - - std::string::iterator port_pos; - - // this is for IPv6 addresses - if (start != url.end() && *start == '[') - { - port_pos = std::find(start, url.end(), ']'); - if (port_pos == url.end()) throw std::runtime_error("invalid hostname syntax '" + url + "'"); - port_pos = std::find(port_pos, url.end(), ':'); - } - else - { - port_pos = std::find(start, url.end(), ':'); - } - - if (port_pos < end) - { - hostname.assign(start, port_pos); - ++port_pos; - try - { - port = boost::lexical_cast(std::string(port_pos, end)); - } - catch(boost::bad_lexical_cast&) - { - throw std::runtime_error("invalid url: \"" + url - + "\", port number expected"); - } - } - else - { - hostname.assign(start, end); - } - - start = end; - return make_tuple(protocol, auth, hostname, port - , std::string(start, url.end())); - } - void tracker_manager::queue_request( - asio::strand& str + io_service& ios , connection_queue& cc , tracker_request req , std::string const& auth @@ -503,63 +197,38 @@ namespace libtorrent if (m_abort && req.event != tracker_request::stopped) return; - try + std::string protocol = req.url.substr(0, req.url.find(':')); + + boost::intrusive_ptr con; + +#ifdef TORRENT_USE_OPENSSL + if (protocol == "http" || protocol == "https") +#else + if (protocol == "http") +#endif { - std::string protocol; - std::string hostname; - int port; - std::string request_string; - - using boost::tuples::ignore; - // TODO: should auth be used here? - boost::tie(protocol, ignore, hostname, port, request_string) - = parse_url_components(req.url); - - boost::intrusive_ptr con; - - if (protocol == "http") - { - con = new http_tracker_connection( - str - , cc - , *this - , req - , hostname - , port - , request_string - , bind_infc - , c - , m_settings - , m_proxy - , auth); - } - else if (protocol == "udp") - { - con = new udp_tracker_connection( - str - , *this - , req - , hostname - , port - , bind_infc - , c - , m_settings); - } - else - { - throw std::runtime_error("unkown protocol in tracker url"); - } - - m_connections.push_back(con); - - boost::shared_ptr cb = con->requester(); - if (cb) cb->m_manager = this; + con = new http_tracker_connection( + ios, cc, *this, req, bind_infc, c + , m_settings, m_proxy, auth); } - catch (std::exception& e) + else if (protocol == "udp") + { + con = new udp_tracker_connection( + ios, cc, *this, req, bind_infc + , c, m_settings, m_proxy); + } + else { if (boost::shared_ptr r = c.lock()) - r->tracker_request_error(req, -1, e.what()); + r->tracker_request_error(req, -1, "unknown protocol in tracker url: " + + req.url); + return; } + + m_connections.push_back(con); + + boost::shared_ptr cb = con->requester(); + if (cb) cb->m_manager = this; } void tracker_manager::abort_all_requests() @@ -589,6 +258,11 @@ namespace libtorrent } // close will remove the entry from m_connections // so no need to pop + +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + boost::shared_ptr rc = c->requester(); + if (rc) rc->debug_log("aborting: " + req.url); +#endif c->close(); } diff --git a/libtorrent/src/udp_socket.cpp b/libtorrent/src/udp_socket.cpp new file mode 100644 index 000000000..78091116a --- /dev/null +++ b/libtorrent/src/udp_socket.cpp @@ -0,0 +1,443 @@ +#include "libtorrent/udp_socket.hpp" +#include "libtorrent/connection_queue.hpp" +#include +#include +#include +#include +#if BOOST_VERSION < 103500 +#include +#else +#include +#endif + +using namespace libtorrent; + +udp_socket::udp_socket(asio::io_service& ios, udp_socket::callback_t const& c + , connection_queue& cc) + : m_callback(c) + , m_ipv4_sock(ios) + , m_ipv6_sock(ios) + , m_bind_port(0) + , m_socks5_sock(ios) + , m_connection_ticket(-1) + , m_cc(cc) + , m_resolver(ios) + , m_tunnel_packets(false) +{ +} + +void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec) +{ + if (ec == asio::error::operation_aborted) return; + + if (m_tunnel_packets) + { + // send udp packets through SOCKS5 server + wrap(ep, p, len, ec); + return; + } + + if (ep.address().is_v4() && m_ipv4_sock.is_open()) + m_ipv4_sock.send_to(asio::buffer(p, len), ep, 0, ec); + else + m_ipv6_sock.send_to(asio::buffer(p, len), ep, 0, ec); +} + +void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_transferred) +{ + if (e == asio::error::operation_aborted) return; + + if (!m_callback) return; + + if (e) + { +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + if (s == &m_ipv4_sock) + m_callback(e, m_v4_ep, 0, 0); + else + m_callback(e, m_v6_ep, 0, 0); +#ifndef BOOST_NO_EXCEPTIONS + } catch(std::exception&) {} +#endif + + // don't stop listening on recoverable errors + if (e != asio::error::host_unreachable + && e != asio::error::fault + && e != asio::error::connection_reset + && e != asio::error::connection_refused + && e != asio::error::connection_aborted + && e != asio::error::message_size) + return; + + if (s == &m_ipv4_sock) + s->async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) + , m_v4_ep, boost::bind(&udp_socket::on_read, this, s, _1, _2)); + else + s->async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) + , m_v6_ep, boost::bind(&udp_socket::on_read, this, s, _1, _2)); + + return; + } + + if (s == &m_ipv4_sock) + { +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + + if (m_tunnel_packets && m_v4_ep == m_proxy_addr) + unwrap(e, m_v4_buf, bytes_transferred); + else + m_callback(e, m_v4_ep, m_v4_buf, bytes_transferred); + +#ifndef BOOST_NO_EXCEPTIONS + } catch(std::exception&) {} +#endif + s->async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) + , m_v4_ep, boost::bind(&udp_socket::on_read, this, s, _1, _2)); + } + else + { +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + + if (m_tunnel_packets && m_v6_ep == m_proxy_addr) + unwrap(e, m_v6_buf, bytes_transferred); + else + m_callback(e, m_v6_ep, m_v6_buf, bytes_transferred); + +#ifndef BOOST_NO_EXCEPTIONS + } catch(std::exception&) {} +#endif + s->async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) + , m_v6_ep, boost::bind(&udp_socket::on_read, this, s, _1, _2)); + } +} + +void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec) +{ + using namespace libtorrent::detail; + + char header[20]; + char* h = header; + + write_uint16(0, h); // reserved + write_uint8(0, h); // fragment + write_uint8(ep.address().is_v4()?1:4, h); // atyp + write_address(ep.address(), h); + write_uint16(ep.port(), h); + + boost::array iovec; + iovec[0] = asio::const_buffer(header, h - header); + iovec[1] = asio::const_buffer(p, len); + + if (m_proxy_addr.address().is_v4() && m_ipv4_sock.is_open()) + m_ipv4_sock.send_to(iovec, m_proxy_addr, 0, ec); + else + m_ipv6_sock.send_to(iovec, m_proxy_addr, 0, ec); +} + +// unwrap the UDP packet from the SOCKS5 header +void udp_socket::unwrap(error_code const& e, char const* buf, int size) +{ + using namespace libtorrent::detail; + + // the minimum socks5 header size + if (size <= 10) return; + + char const* p = buf; + p += 2; // reserved + int frag = read_uint8(p); + // fragmentation is not supported + if (frag != 0) return; + + udp::endpoint sender; + + int atyp = read_uint8(p); + if (atyp == 1) + { + // IPv4 + sender = read_v4_endpoint(p); + } + else if (atyp == 4) + { + // IPv6 + sender = read_v6_endpoint(p); + } + else + { + // domain name not supported + return; + } + + m_callback(e, sender, p, size - (p - buf)); +} + +void udp_socket::close() +{ + error_code ec; + m_ipv4_sock.close(ec); + m_ipv6_sock.close(ec); + m_socks5_sock.close(ec); + m_callback.clear(); + if (m_connection_ticket >= 0) + { + m_cc.done(m_connection_ticket); + m_connection_ticket = -1; + } +} + +void udp_socket::bind(udp::endpoint const& ep, error_code& ec) +{ + if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec); + if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec); + + if (ep.address().is_v4()) + { + m_ipv4_sock.open(udp::v4(), ec); + if (ec) return; + m_ipv4_sock.bind(ep, ec); + if (ec) return; + m_ipv4_sock.async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) + , m_v4_ep, boost::bind(&udp_socket::on_read, this, &m_ipv4_sock, _1, _2)); + } + else + { + m_ipv6_sock.set_option(v6only(true), ec); + if (ec) return; + m_ipv6_sock.bind(ep, ec); + if (ec) return; + m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) + , m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2)); + } + m_bind_port = ep.port(); +} + +void udp_socket::bind(int port) +{ + error_code ec; + + if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec); + if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec); + + m_ipv4_sock.open(udp::v4(), ec); + if (!ec) + { + m_ipv4_sock.bind(udp::endpoint(address_v4::any(), port), ec); + m_ipv4_sock.async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) + , m_v4_ep, boost::bind(&udp_socket::on_read, this, &m_ipv4_sock, _1, _2)); + } + m_ipv6_sock.open(udp::v6(), ec); + if (!ec) + { + m_ipv6_sock.set_option(v6only(true), ec); + m_ipv6_sock.bind(udp::endpoint(address_v6::any(), port), ec); + m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) + , m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2)); + } + m_bind_port = port; +} + +void udp_socket::set_proxy_settings(proxy_settings const& ps) +{ + error_code ec; + m_socks5_sock.close(ec); + m_tunnel_packets = false; + + m_proxy_settings = ps; + + if (ps.type == proxy_settings::socks5 + || ps.type == proxy_settings::socks5_pw) + { + // connect to socks5 server and open up the UDP tunnel + tcp::resolver::query q(ps.hostname + , boost::lexical_cast(ps.port)); + m_resolver.async_resolve(q, boost::bind( + &udp_socket::on_name_lookup, this, _1, _2)); + } +} + +void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i) +{ + if (e) return; + m_proxy_addr.address(i->endpoint().address()); + m_proxy_addr.port(i->endpoint().port()); + m_cc.enqueue(boost::bind(&udp_socket::on_connect, this, _1) + , boost::bind(&udp_socket::on_timeout, this), seconds(10)); +} + +void udp_socket::on_timeout() +{ + error_code ec; + m_socks5_sock.close(ec); + m_connection_ticket = -1; +} + +void udp_socket::on_connect(int ticket) +{ + m_connection_ticket = ticket; + error_code ec; + m_socks5_sock.open(m_proxy_addr.address().is_v4()?tcp::v4():tcp::v6(), ec); + m_socks5_sock.async_connect(tcp::endpoint(m_proxy_addr.address(), m_proxy_addr.port()) + , boost::bind(&udp_socket::on_connected, this, _1)); +} + +void udp_socket::on_connected(error_code const& e) +{ + m_cc.done(m_connection_ticket); + m_connection_ticket = -1; + if (e) return; + + using namespace libtorrent::detail; + + // send SOCKS5 authentication methods + char* p = &m_tmp_buf[0]; + write_uint8(5, p); // SOCKS VERSION 5 + if (m_proxy_settings.username.empty() + || m_proxy_settings.type == proxy_settings::socks5) + { + write_uint8(1, p); // 1 authentication method (no auth) + write_uint8(0, p); // no authentication + } + else + { + write_uint8(2, p); // 2 authentication methods + write_uint8(0, p); // no authentication + write_uint8(2, p); // username/password + } + asio::async_write(m_socks5_sock, asio::buffer(m_tmp_buf, p - m_tmp_buf) + , boost::bind(&udp_socket::handshake1, this, _1)); +} + +void udp_socket::handshake1(error_code const& e) +{ + if (e) return; + + asio::async_read(m_socks5_sock, asio::buffer(m_tmp_buf, 2) + , boost::bind(&udp_socket::handshake2, this, _1)); +} + +void udp_socket::handshake2(error_code const& e) +{ + if (e) return; + + using namespace libtorrent::detail; + + char* p = &m_tmp_buf[0]; + int version = read_uint8(p); + int method = read_uint8(p); + + if (version < 5) return; + + if (method == 0) + { + socks_forward_udp(); + } + else if (method == 2) + { + if (m_proxy_settings.username.empty()) + { + error_code ec; + m_socks5_sock.close(ec); + return; + } + + // start sub-negotiation + char* p = &m_tmp_buf[0]; + write_uint8(1, p); + write_uint8(m_proxy_settings.username.size(), p); + write_string(m_proxy_settings.username, p); + write_uint8(m_proxy_settings.password.size(), p); + write_string(m_proxy_settings.password, p); + asio::async_write(m_socks5_sock, asio::buffer(m_tmp_buf, p - m_tmp_buf) + , boost::bind(&udp_socket::handshake3, this, _1)); + } + else + { + error_code ec; + m_socks5_sock.close(ec); + return; + } +} + +void udp_socket::handshake3(error_code const& e) +{ + if (e) return; + + asio::async_read(m_socks5_sock, asio::buffer(m_tmp_buf, 2) + , boost::bind(&udp_socket::handshake4, this, _1)); +} + +void udp_socket::handshake4(error_code const& e) +{ + if (e) return; + + using namespace libtorrent::detail; + + char* p = &m_tmp_buf[0]; + int version = read_uint8(p); + int status = read_uint8(p); + + if (version != 1) return; + if (status != 0) return; + + socks_forward_udp(); +} + +void udp_socket::socks_forward_udp() +{ + using namespace libtorrent::detail; + + // send SOCKS5 UDP command + char* p = &m_tmp_buf[0]; + write_uint8(5, p); // SOCKS VERSION 5 + write_uint8(3, p); // UDP ASSOCIATE command + write_uint8(0, p); // reserved + write_uint8(0, p); // ATYP IPv4 + write_uint32(0, p); // IP any + write_uint16(m_bind_port, p); + + asio::async_write(m_socks5_sock, asio::buffer(m_tmp_buf, p - m_tmp_buf) + , boost::bind(&udp_socket::connect1, this, _1)); +} + +void udp_socket::connect1(error_code const& e) +{ + if (e) return; + + asio::async_read(m_socks5_sock, asio::buffer(m_tmp_buf, 10) + , boost::bind(&udp_socket::connect2, this, _1)); +} + +void udp_socket::connect2(error_code const& e) +{ + if (e) return; + + using namespace libtorrent::detail; + + char* p = &m_tmp_buf[0]; + int version = read_uint8(p); // VERSION + int status = read_uint8(p); // STATUS + read_uint8(p); // RESERVED + int atyp = read_uint8(p); // address type + + if (version != 5) return; + if (status != 0) return; + + if (atyp == 1) + { + m_proxy_addr.address(address_v4(read_uint32(p))); + m_proxy_addr.port(read_uint16(p)); + } + else + { + // in this case we need to read more data from the socket + TORRENT_ASSERT(false && "not implemented yet!"); + } + + m_tunnel_packets = true; +} + diff --git a/libtorrent/src/udp_tracker_connection.cpp b/libtorrent/src/udp_tracker_connection.cpp index 0ad38ef86..e19d5696d 100755 --- a/libtorrent/src/udp_tracker_connection.cpp +++ b/libtorrent/src/udp_tracker_connection.cpp @@ -52,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include "libtorrent/tracker_manager.hpp" +#include "libtorrent/parse_url.hpp" #include "libtorrent/udp_tracker_connection.hpp" #include "libtorrent/io.hpp" @@ -62,8 +63,7 @@ namespace udp_connection_retries = 4, udp_announce_retries = 15, udp_connect_timeout = 15, - udp_announce_timeout = 10, - udp_buffer_size = 2048 + udp_announce_timeout = 10 }; } @@ -74,36 +74,56 @@ namespace libtorrent { udp_tracker_connection::udp_tracker_connection( - asio::strand& str + io_service& ios + , connection_queue& cc , tracker_manager& man , tracker_request const& req - , std::string const& hostname - , unsigned short port , address bind_infc , boost::weak_ptr c - , session_settings const& stn) - : tracker_connection(man, req, str, bind_infc, c) + , session_settings const& stn + , proxy_settings const& proxy) + : tracker_connection(man, req, ios, bind_infc, c) , m_man(man) - , m_strand(str) - , m_name_lookup(m_strand.io_service()) - , m_socket(m_strand.io_service()) + , m_name_lookup(ios) + , m_socket(ios, boost::bind(&udp_tracker_connection::on_receive, self(), _1, _2, _3, _4), cc) , m_transaction_id(0) , m_connection_id(0) , m_settings(stn) , m_attempts(0) + , m_state(action_error) { + m_socket.set_proxy_settings(proxy); + + std::string hostname; + int port; + char const* error; + + using boost::tuples::ignore; + boost::tie(ignore, ignore, hostname, port, ignore, error) + = parse_url_components(req.url); + + if (error) + { + fail(-1, error); + return; + } + udp::resolver::query q(hostname, boost::lexical_cast(port)); m_name_lookup.async_resolve(q - , m_strand.wrap(boost::bind( - &udp_tracker_connection::name_lookup, self(), _1, _2))); + , boost::bind( + &udp_tracker_connection::name_lookup, self(), _1, _2)); set_timeout(req.event == tracker_request::stopped ? m_settings.stop_tracker_timeout : m_settings.tracker_completion_timeout , m_settings.tracker_receive_timeout); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING + boost::shared_ptr cb = requester(); + if (cb) cb->debug_log(("*** UDP_TRACKER [ initiating name lookup: " + hostname + " ]").c_str()); +#endif } - void udp_tracker_connection::name_lookup(asio::error_code const& error - , udp::resolver::iterator i) try + void udp_tracker_connection::name_lookup(error_code const& error + , udp::resolver::iterator i) { if (error == asio::error::operation_aborted) return; if (error || i == udp::resolver::iterator()) @@ -113,8 +133,8 @@ namespace libtorrent } boost::shared_ptr cb = requester(); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (cb) cb->debug_log("udp tracker name lookup successful"); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING + if (cb) cb->debug_log("*** UDP_TRACKER [ name lookup successful ]"); #endif restart_read_timeout(); @@ -133,7 +153,7 @@ namespace libtorrent { std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6"; std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6"; - cb->tracker_warning("the tracker only resolves to an " + cb->tracker_warning(tracker_req(), "the tracker only resolves to an " + tracker_address_type + " address, and you're listening on an " + bind_address_type + " socket. This may prevent you from receiving incoming connections."); } @@ -145,35 +165,134 @@ namespace libtorrent if (cb) cb->m_tracker_address = tcp::endpoint(target_address.address(), target_address.port()); m_target = target_address; - m_socket.open(target_address.protocol()); - m_socket.bind(udp::endpoint(bind_interface(), 0)); - m_socket.connect(target_address); + error_code ec; + m_socket.bind(udp::endpoint(bind_interface(), 0), ec); + if (ec) + { + fail(-1, ec.message().c_str()); + return; + } send_udp_connect(); } - catch (std::exception& e) - { - fail(-1, e.what()); - }; void udp_tracker_connection::on_timeout() { - asio::error_code ec; - m_socket.close(ec); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + boost::shared_ptr cb = requester(); + if (cb) cb->debug_log("*** UDP_TRACKER [ timed out ]"); +#endif + m_socket.close(); m_name_lookup.cancel(); fail_timeout(); } void udp_tracker_connection::close() { - asio::error_code ec; - m_socket.close(ec); + error_code ec; + m_socket.close(); m_name_lookup.cancel(); tracker_connection::close(); } + void udp_tracker_connection::on_receive(error_code const& e + , udp::endpoint const& ep, char const* buf, int size) + { + // ignore resposes before we've sent any requests + if (m_state == action_error) return; + + if (!m_socket.is_open()) return; // the operation was aborted + + // ignore packet not sent from the tracker + if (m_target != ep) return; + + if (e) fail(-1, e.message().c_str()); + +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING + boost::shared_ptr cb = requester(); + if (cb) + { + std::stringstream msg; + msg << "<== UDP_TRACKER_PACKET [ size: " << size << " ]"; + cb->debug_log(msg.str()); + } +#endif + + // ignore packets smaller than 8 bytes + if (size < 8) return; + + restart_read_timeout(); + + const char* ptr = buf; + int action = detail::read_int32(ptr); + int transaction = detail::read_int32(ptr); + +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING + if (cb) + { + std::stringstream msg; + msg << "*** UDP_TRACKER_PACKET [ acton: " << action << " ]"; + cb->debug_log(msg.str()); + } +#endif + + // ignore packets with incorrect transaction id + if (m_transaction_id != transaction) return; + + if (action == action_error) + { + fail(-1, std::string(ptr, size - 8).c_str()); + return; + } + + // ignore packets that's not a response to our message + if (action != m_state) return; + +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING + if (cb) + { + std::stringstream msg; + msg << "*** UDP_TRACKER_RESPONSE [ cid: " << m_connection_id << " ]"; + cb->debug_log(msg.str()); + } +#endif + + switch (m_state) + { + case action_connect: + on_connect_response(buf, size); + break; + case action_announce: + on_announce_response(buf, size); + break; + case action_scrape: + on_scrape_response(buf, size); + break; + default: break; + } + } + + void udp_tracker_connection::on_connect_response(char const* buf, int size) + { + // ignore packets smaller than 16 bytes + if (size < 16) return; + + restart_read_timeout(); + buf += 8; // skip header + + // reset transaction + m_transaction_id = 0; + m_attempts = 0; + m_connection_id = detail::read_int64(buf); + + if (tracker_req().kind == tracker_request::announce_request) + send_udp_announce(); + else if (tracker_req().kind == tracker_request::scrape_request) + send_udp_scrape(); + } + void udp_tracker_connection::send_udp_connect() { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING boost::shared_ptr cb = requester(); if (cb) { @@ -183,170 +302,27 @@ namespace libtorrent #endif if (!m_socket.is_open()) return; // the operation was aborted - char send_buf[16]; - char* ptr = send_buf; + char buf[16]; + char* ptr = buf; if (m_transaction_id == 0) m_transaction_id = rand() ^ (rand() << 16); - // connection_id detail::write_uint32(0x417, ptr); - detail::write_uint32(0x27101980, ptr); - // action (connect) - detail::write_int32(action_connect, ptr); - // transaction_id - detail::write_int32(m_transaction_id, ptr); + detail::write_uint32(0x27101980, ptr); // connection_id + detail::write_int32(action_connect, ptr); // action (connect) + detail::write_int32(m_transaction_id, ptr); // transaction_id + TORRENT_ASSERT(ptr - buf == sizeof(buf)); - m_socket.send(asio::buffer((void*)send_buf, 16), 0); + error_code ec; + m_socket.send(m_target, buf, 16, ec); + m_state = action_connect; ++m_attempts; - m_buffer.resize(udp_buffer_size); - m_socket.async_receive_from(asio::buffer(m_buffer), m_sender - , boost::bind(&udp_tracker_connection::connect_response, self(), _1, _2)); - } - - void udp_tracker_connection::connect_response(asio::error_code const& error - , std::size_t bytes_transferred) try - { - if (error == asio::error::operation_aborted) return; - if (!m_socket.is_open()) return; // the operation was aborted - if (error) + if (ec) { - fail(-1, error.message().c_str()); + fail(-1, ec.message().c_str()); return; } - - if (m_target != m_sender) - { - // this packet was not received from the tracker - m_socket.async_receive_from(asio::buffer(m_buffer), m_sender - , boost::bind(&udp_tracker_connection::connect_response, self(), _1, _2)); - return; - } - - if (bytes_transferred >= udp_buffer_size) - { - fail(-1, "udp response too big"); - return; - } - - if (bytes_transferred < 8) - { - fail(-1, "got a message with size < 8"); - return; - } - - restart_read_timeout(); - - const char* ptr = &m_buffer[0]; - int action = detail::read_int32(ptr); - int transaction = detail::read_int32(ptr); - - if (action == action_error) - { - fail(-1, std::string(ptr, bytes_transferred - 8).c_str()); - return; - } - - if (action != action_connect) - { - fail(-1, "invalid action in connect reply"); - return; - } - - if (m_transaction_id != transaction) - { - fail(-1, "incorrect transaction id"); - return; - } - - if (bytes_transferred < 16) - { - fail(-1, "udp_tracker_connection: " - "got a message with size < 16"); - return; - } - // reset transaction - m_transaction_id = 0; - m_attempts = 0; - m_connection_id = detail::read_int64(ptr); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - boost::shared_ptr cb = requester(); - if (cb) - { - cb->debug_log("<== UDP_TRACKER_CONNECT_RESPONSE [" - + lexical_cast(m_connection_id) + "]"); - } -#endif - - if (tracker_req().kind == tracker_request::announce_request) - send_udp_announce(); - else if (tracker_req().kind == tracker_request::scrape_request) - send_udp_scrape(); - } - catch (std::exception& e) - { - fail(-1, e.what()); - } - - void udp_tracker_connection::send_udp_announce() - { - if (m_transaction_id == 0) - m_transaction_id = rand() ^ (rand() << 16); - - if (!m_socket.is_open()) return; // the operation was aborted - - std::vector buf; - std::back_insert_iterator > out(buf); - - tracker_request const& req = tracker_req(); - - // connection_id - detail::write_int64(m_connection_id, out); - // action (announce) - detail::write_int32(action_announce, out); - // transaction_id - detail::write_int32(m_transaction_id, out); - // info_hash - std::copy(req.info_hash.begin(), req.info_hash.end(), out); - // peer_id - std::copy(req.pid.begin(), req.pid.end(), out); - // downloaded - detail::write_int64(req.downloaded, out); - // left - detail::write_int64(req.left, out); - // uploaded - detail::write_int64(req.uploaded, out); - // event - detail::write_int32(req.event, out); - // ip address - if (m_settings.announce_ip != address() && m_settings.announce_ip.is_v4()) - detail::write_uint32(m_settings.announce_ip.to_v4().to_ulong(), out); - else - detail::write_int32(0, out); - // key - detail::write_int32(req.key, out); - // num_want - detail::write_int32(req.num_want, out); - // port - detail::write_uint16(req.listen_port, out); - // extensions - detail::write_uint16(0, out); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - boost::shared_ptr cb = requester(); - if (cb) - { - cb->debug_log("==> UDP_TRACKER_ANNOUNCE [" - + lexical_cast(req.info_hash) + "]"); - } -#endif - - m_socket.send(asio::buffer(buf), 0); - ++m_attempts; - - m_socket.async_receive_from(asio::buffer(m_buffer), m_sender - , bind(&udp_tracker_connection::announce_response, self(), _1, _2)); } void udp_tracker_connection::send_udp_scrape() @@ -356,97 +332,48 @@ namespace libtorrent if (!m_socket.is_open()) return; // the operation was aborted - std::vector buf; - std::back_insert_iterator > out(buf); + char buf[8 + 4 + 4 + 20]; + char* out = buf; - // connection_id - detail::write_int64(m_connection_id, out); - // action (scrape) - detail::write_int32(action_scrape, out); - // transaction_id - detail::write_int32(m_transaction_id, out); + detail::write_int64(m_connection_id, out); // connection_id + detail::write_int32(action_scrape, out); // action (scrape) + detail::write_int32(m_transaction_id, out); // transaction_id // info_hash std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end(), out); + out += 20; + TORRENT_ASSERT(out - buf == sizeof(buf)); - m_socket.send(asio::buffer(&buf[0], buf.size()), 0); + error_code ec; + m_socket.send(m_target, buf, sizeof(buf), ec); + m_state = action_scrape; ++m_attempts; - - m_socket.async_receive_from(asio::buffer(m_buffer), m_sender - , bind(&udp_tracker_connection::scrape_response, self(), _1, _2)); + if (ec) + { + fail(-1, ec.message().c_str()); + return; + } } - void udp_tracker_connection::announce_response(asio::error_code const& error - , std::size_t bytes_transferred) try + void udp_tracker_connection::on_announce_response(char const* buf, int size) { - if (error == asio::error::operation_aborted) return; - if (!m_socket.is_open()) return; // the operation was aborted - if (error) - { - fail(-1, error.message().c_str()); - return; - } - - if (m_target != m_sender) - { - // this packet was not received from the tracker - m_socket.async_receive_from(asio::buffer(m_buffer), m_sender - , bind(&udp_tracker_connection::connect_response, self(), _1, _2)); - return; - } - - if (bytes_transferred >= udp_buffer_size) - { - fail(-1, "udp response too big"); - return; - } - - if (bytes_transferred < 8) - { - fail(-1, "got a message with size < 8"); - return; - } + if (size < 20) return; restart_read_timeout(); - char* buf = &m_buffer[0]; - int action = detail::read_int32(buf); - int transaction = detail::read_int32(buf); - - if (transaction != m_transaction_id) - { - fail(-1, "incorrect transaction id"); - return; - } - - if (action == action_error) - { - fail(-1, std::string(buf, bytes_transferred - 8).c_str()); - return; - } - - if (action != action_announce) - { - fail(-1, "invalid action in announce response"); - return; - } - - if (bytes_transferred < 20) - { - fail(-1, "got a message with size < 20"); - return; - } + buf += 8; // skip header + restart_read_timeout(); int interval = detail::read_int32(buf); int incomplete = detail::read_int32(buf); int complete = detail::read_int32(buf); - int num_peers = (bytes_transferred - 20) / 6; - if ((bytes_transferred - 20) % 6 != 0) + int num_peers = (size - 20) / 6; + if ((size - 20) % 6 != 0) { fail(-1, "invalid udp tracker response length"); return; } boost::shared_ptr cb = requester(); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING if (cb) { cb->debug_log("<== UDP_TRACKER_ANNOUNCE_RESPONSE"); @@ -462,6 +389,7 @@ namespace libtorrent std::vector peer_list; for (int i = 0; i < num_peers; ++i) { + // TODO: don't use a string here peer_entry e; std::stringstream s; s << (int)detail::read_uint8(buf) << "."; @@ -475,50 +403,17 @@ namespace libtorrent } cb->tracker_response(tracker_req(), peer_list, interval - , complete, incomplete); + , complete, incomplete, address()); m_man.remove_request(this); close(); - return; } - catch (std::exception& e) + + void udp_tracker_connection::on_scrape_response(char const* buf, int size) { - fail(-1, e.what()); - }; // msvc 7.1 seems to require this - - void udp_tracker_connection::scrape_response(asio::error_code const& error - , std::size_t bytes_transferred) try - { - if (error == asio::error::operation_aborted) return; - if (!m_socket.is_open()) return; // the operation was aborted - if (error) - { - fail(-1, error.message().c_str()); - return; - } - - if (m_target != m_sender) - { - // this packet was not received from the tracker - m_socket.async_receive_from(asio::buffer(m_buffer), m_sender - , bind(&udp_tracker_connection::connect_response, self(), _1, _2)); - return; - } - - if (bytes_transferred >= udp_buffer_size) - { - fail(-1, "udp response too big"); - return; - } - - if (bytes_transferred < 8) - { - fail(-1, "got a message with size < 8"); - return; - } + buf += 8; // skip header restart_read_timeout(); - char* buf = &m_buffer[0]; int action = detail::read_int32(buf); int transaction = detail::read_int32(buf); @@ -530,7 +425,7 @@ namespace libtorrent if (action == action_error) { - fail(-1, std::string(buf, bytes_transferred - 8).c_str()); + fail(-1, std::string(buf, size - 8).c_str()); return; } @@ -540,7 +435,7 @@ namespace libtorrent return; } - if (bytes_transferred < 20) + if (size < 20) { fail(-1, "got a message with size < 20"); return; @@ -553,7 +448,6 @@ namespace libtorrent boost::shared_ptr cb = requester(); if (!cb) { - m_man.remove_request(this); close(); return; } @@ -564,9 +458,60 @@ namespace libtorrent m_man.remove_request(this); close(); } - catch (std::exception& e) + + void udp_tracker_connection::send_udp_announce() { - fail(-1, e.what()); + if (m_transaction_id == 0) + m_transaction_id = rand() ^ (rand() << 16); + + if (!m_socket.is_open()) return; // the operation was aborted + + char buf[8 + 4 + 4 + 20 + 20 + 8 + 8 + 8 + 4 + 4 + 4 + 4 + 2 + 2]; + char* out = buf; + + tracker_request const& req = tracker_req(); + + detail::write_int64(m_connection_id, out); // connection_id + detail::write_int32(action_announce, out); // action (announce) + detail::write_int32(m_transaction_id, out); // transaction_id + std::copy(req.info_hash.begin(), req.info_hash.end(), out); // info_hash + out += 20; + std::copy(req.pid.begin(), req.pid.end(), out); // peer_id + out += 20; + detail::write_int64(req.downloaded, out); // downloaded + detail::write_int64(req.left, out); // left + detail::write_int64(req.uploaded, out); // uploaded + detail::write_int32(req.event, out); // event + // ip address + if (m_settings.announce_ip != address() && m_settings.announce_ip.is_v4()) + detail::write_uint32(m_settings.announce_ip.to_v4().to_ulong(), out); + else + detail::write_int32(0, out); + detail::write_int32(req.key, out); // key + detail::write_int32(req.num_want, out); // num_want + detail::write_uint16(req.listen_port, out); // port + detail::write_uint16(0, out); // extensions + + TORRENT_ASSERT(out - buf == sizeof(buf)); + +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING + boost::shared_ptr cb = requester(); + if (cb) + { + cb->debug_log("==> UDP_TRACKER_ANNOUNCE [" + + lexical_cast(req.info_hash) + "]"); + } +#endif + + error_code ec; + m_socket.send(m_target, buf, sizeof(buf), ec); + m_state = action_announce; + ++m_attempts; + if (ec) + { + fail(-1, ec.message().c_str()); + return; + } } } diff --git a/libtorrent/src/upnp.cpp b/libtorrent/src/upnp.cpp index 7a37635ed..d4cc8a4ca 100644 --- a/libtorrent/src/upnp.cpp +++ b/libtorrent/src/upnp.cpp @@ -35,15 +35,20 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket.hpp" #include "libtorrent/upnp.hpp" #include "libtorrent/io.hpp" -#include "libtorrent/http_tracker_connection.hpp" +#include "libtorrent/parse_url.hpp" #include "libtorrent/xml_parse.hpp" #include "libtorrent/connection_queue.hpp" #include "libtorrent/enum_net.hpp" #include #include +#if BOOST_VERSION < 103500 #include #include +#else +#include +#include +#endif #include #include @@ -54,42 +59,60 @@ POSSIBILITY OF SUCH DAMAGE. using boost::bind; using namespace libtorrent; -namespace libtorrent -{ - bool is_local(address const& a); - address guess_local_address(asio::io_service&); -} - upnp::upnp(io_service& ios, connection_queue& cc , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb, bool ignore_nonrouters) - : m_udp_local_port(0) - , m_tcp_local_port(0) - , m_user_agent(user_agent) + , portmap_callback_t const& cb, bool ignore_nonrouters, void* state) + : m_user_agent(user_agent) , m_callback(cb) , m_retry_count(0) , m_io_service(ios) - , m_strand(ios) , m_socket(ios, udp::endpoint(address_v4::from_string("239.255.255.250"), 1900) , bind(&upnp::on_reply, self(), _1, _2, _3), false) , m_broadcast_timer(ios) , m_refresh_timer(ios) , m_disabled(false) , m_closing(false) - , m_ignore_outside_network(ignore_nonrouters) + , m_ignore_non_routers(ignore_nonrouters) , m_cc(cc) { #ifdef TORRENT_UPNP_LOGGING m_log.open("upnp.log", std::ios::in | std::ios::out | std::ios::trunc); #endif m_retry_count = 0; + + if (state) + { + upnp_state_t* s = (upnp_state_t*)state; + m_devices.swap(s->devices); + m_mappings.swap(s->mappings); + delete s; + } +} + +void* upnp::drain_state() +{ + upnp_state_t* s = new upnp_state_t; + s->mappings.swap(m_mappings); + + for (std::set::iterator i = m_devices.begin() + , end(m_devices.end()); i != end; ++i) + i->upnp_connection.reset(); + s->devices.swap(m_devices); + return s; } upnp::~upnp() { } -void upnp::discover_device() try +void upnp::discover_device() +{ + mutex_t::scoped_lock l(m_mutex); + + discover_device_impl(); +} + +void upnp::discover_device_impl() { const char msearch[] = "M-SEARCH * HTTP/1.1\r\n" @@ -99,7 +122,7 @@ void upnp::discover_device() try "MX:3\r\n" "\r\n\r\n"; - asio::error_code ec; + error_code ec; #ifdef TORRENT_DEBUG_UPNP // simulate packet loss if (m_retry_count & 1) @@ -113,12 +136,12 @@ void upnp::discover_device() try << " ==> Broadcast FAILED: " << ec.message() << std::endl << "aborting" << std::endl; #endif - disable(); + disable(ec.message().c_str()); return; } ++m_retry_count; - m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count)); + m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec); m_broadcast_timer.async_wait(bind(&upnp::resend_request , self(), _1)); @@ -127,59 +150,100 @@ void upnp::discover_device() try << " ==> Broadcasting search for rootdevice" << std::endl; #endif } -catch (std::exception&) -{ - disable(); -}; -void upnp::set_mappings(int tcp, int udp) +// returns a reference to a mapping or -1 on failure +int upnp::add_mapping(upnp::protocol_type p, int external_port, int local_port) { + mutex_t::scoped_lock l(m_mutex); + #ifdef TORRENT_UPNP_LOGGING m_log << time_now_string() - << " *** set mappings " << tcp << " " << udp; + << " *** add mapping [ proto: " << (p == tcp?"tcp":"udp") + << " ext_port: " << external_port + << " local_port :" << local_port << " ]"; if (m_disabled) m_log << " DISABLED"; m_log << std::endl; #endif + if (m_disabled) return -1; - if (m_disabled) return; - if (udp != 0) m_udp_local_port = udp; - if (tcp != 0) m_tcp_local_port = tcp; + std::vector::iterator i = std::find_if( + m_mappings.begin(), m_mappings.end() + , boost::bind(&global_mapping_t::protocol, _1) == int(none)); + + if (i == m_mappings.end()) + { + m_mappings.push_back(global_mapping_t()); + i = m_mappings.end() - 1; + } + + i->protocol = p; + i->external_port = external_port; + i->local_port = local_port; + + int mapping_index = i - m_mappings.begin(); for (std::set::iterator i = m_devices.begin() , end(m_devices.end()); i != end; ++i) { rootdevice& d = const_cast(*i); TORRENT_ASSERT(d.magic == 1337); - if (d.mapping[0].local_port != m_tcp_local_port) - { - if (d.mapping[0].external_port == 0) - d.mapping[0].external_port = m_tcp_local_port; - d.mapping[0].local_port = m_tcp_local_port; - d.mapping[0].need_update = true; - } - if (d.mapping[1].local_port != m_udp_local_port) - { - if (d.mapping[1].external_port == 0) - d.mapping[1].external_port = m_udp_local_port; - d.mapping[1].local_port = m_udp_local_port; - d.mapping[1].need_update = true; - } - if (d.service_namespace - && (d.mapping[0].need_update || d.mapping[1].need_update)) - map_port(d, 0); + + if (int(d.mapping.size()) <= mapping_index) + d.mapping.resize(mapping_index + 1); + mapping_t& m = d.mapping[mapping_index]; + + m.action = mapping_t::action_add; + m.protocol = p; + m.external_port = external_port; + m.local_port = local_port; + + if (d.service_namespace) update_map(d, mapping_index); + } + + return mapping_index; +} + +void upnp::delete_mapping(int mapping) +{ + mutex_t::scoped_lock l(m_mutex); + + if (mapping <= int(m_mappings.size())) return; + + global_mapping_t& m = m_mappings[mapping]; + +#ifdef TORRENT_UPNP_LOGGING + m_log << time_now_string() + << " *** delete mapping [ proto: " << (m.protocol == tcp?"tcp":"udp") + << " ext_port:" << m.external_port + << " local_port:" << m.local_port << " ]"; + m_log << std::endl; +#endif + + if (m.protocol == none) return; + + for (std::set::iterator i = m_devices.begin() + , end(m_devices.end()); i != end; ++i) + { + rootdevice& d = const_cast(*i); + TORRENT_ASSERT(d.magic == 1337); + + TORRENT_ASSERT(mapping < int(d.mapping.size())); + d.mapping[mapping].action = mapping_t::action_delete; + + if (d.service_namespace) update_map(d, mapping); } } -void upnp::resend_request(asio::error_code const& e) -#ifndef NDEBUG -try -#endif +void upnp::resend_request(error_code const& e) { if (e) return; + + mutex_t::scoped_lock l(m_mutex); + if (m_retry_count < 9 && (m_devices.empty() || m_retry_count < 4)) { - discover_device(); + discover_device_impl(); return; } @@ -190,7 +254,7 @@ try << " *** Got no response in 9 retries. Giving up, " "disabling UPnP." << std::endl; #endif - disable(); + disable("no UPnP router found"); return; } @@ -213,7 +277,7 @@ try d.upnp_connection.reset(new http_connection(m_io_service , m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2 , boost::ref(d), _5))); - d.upnp_connection->get(d.url); + d.upnp_connection->get(d.url, seconds(30), 1); } catch (std::exception& e) { @@ -228,19 +292,12 @@ try } } } -#ifndef NDEBUG -catch (std::exception&) -{ - TORRENT_ASSERT(false); -}; -#endif void upnp::on_reply(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred) -#ifndef NDEBUG -try -#endif { + mutex_t::scoped_lock l(m_mutex); + using namespace libtorrent::detail; // parse out the url for the device @@ -269,8 +326,34 @@ try Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0 */ - asio::error_code ec; - if (m_ignore_outside_network && !in_local_network(m_io_service, from.address(), ec)) + error_code ec; + if (!in_local_network(m_io_service, from.address(), ec)) + { +#ifdef TORRENT_UPNP_LOGGING + if (ec) + { + m_log << time_now_string() << " <== (" << from << ") error: " + << ec.message() << std::endl; + } + else + { + m_log << time_now_string() << " <== (" << from << ") UPnP device " + "ignored because it's not on our local network "; + std::vector const& net = enum_net_interfaces(m_io_service, ec); + for (std::vector::const_iterator i = net.begin() + , end(net.end()); i != end; ++i) + { + m_log << "(" << i->interface_address << ", " << i->netmask << ") "; + } + m_log << std::endl; + } +#endif + return; + } + + std::vector routes = enum_routes(m_io_service, ec); + if (m_ignore_non_routers && std::find_if(routes.begin(), routes.end() + , bind(&ip_route::gateway, _1) == from.address()) == routes.end()) { // this upnp device is filtered because it's not in the // list of configured routers @@ -282,13 +365,12 @@ try } else { - std::vector const& net = enum_net_interfaces(m_io_service, ec); m_log << time_now_string() << " <== (" << from << ") UPnP device " - "ignored because it's not on our network "; - for (std::vector::const_iterator i = net.begin() - , end(net.end()); i != end; ++i) + "ignored because it's not a router on our network "; + for (std::vector::const_iterator i = routes.begin() + , end(routes.end()); i != end; ++i) { - m_log << "(" << i->interface_address << ", " << i->netmask << ") "; + m_log << "(" << i->gateway << ", " << i->netmask << ") "; } m_log << std::endl; } @@ -297,17 +379,14 @@ try } http_parser p; - try + bool error = false; + p.incoming(buffer::const_interval(buffer + , buffer + bytes_transferred), error); + if (error) { - p.incoming(buffer::const_interval(buffer - , buffer + bytes_transferred)); - } - catch (std::exception& e) - { - (void)e; #ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== (" << from << ") Rootdevice responded with incorrect HTTP packet. Ignoring device (" << e.what() << ")" << std::endl; + m_log << time_now_string() << " <== (" << from << ") Rootdevice " + "responded with incorrect HTTP packet. Ignoring device" << std::endl; #endif return; } @@ -358,18 +437,17 @@ try std::string protocol; std::string auth; + char const* error; // we don't have this device in our list. Add it - try - { - boost::tie(protocol, auth, d.hostname, d.port, d.path) - = parse_url_components(d.url); - } - catch (std::exception& e) + boost::tie(protocol, auth, d.hostname, d.port, d.path, error) + = parse_url_components(d.url); + + if (error) { #ifdef TORRENT_UPNP_LOGGING m_log << time_now_string() - << " <== (" << from << ") invalid url: '" << d.url - << "'. Ignoring device" << std::endl; + << " <== (" << from << ") Rootdevice advertized an invalid url: '" << d.url + << "'. " << error << ". Ignoring device" << std::endl; #endif return; } @@ -412,25 +490,16 @@ try return; } - if (m_tcp_local_port != 0) + TORRENT_ASSERT(d.mapping.empty()); + for (std::vector::iterator j = m_mappings.begin() + , end(m_mappings.end()); j != end; ++j) { - d.mapping[0].need_update = true; - d.mapping[0].local_port = m_tcp_local_port; - if (d.mapping[0].external_port == 0) - d.mapping[0].external_port = d.mapping[0].local_port; -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() << " *** Mapping 0 will be updated" << std::endl; -#endif - } - if (m_udp_local_port != 0) - { - d.mapping[1].need_update = true; - d.mapping[1].local_port = m_udp_local_port; - if (d.mapping[1].external_port == 0) - d.mapping[1].external_port = d.mapping[1].local_port; -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() << " *** Mapping 1 will be updated" << std::endl; -#endif + mapping_t m; + m.action = mapping_t::action_add; + m.local_port = j->local_port; + m.external_port = j->external_port; + m.protocol = j->protocol; + d.mapping.push_back(m); } boost::tie(i, boost::tuples::ignore) = m_devices.insert(d); } @@ -440,7 +509,8 @@ try // just to make sure we find all devices if (m_retry_count >= 4 && !m_devices.empty()) { - m_broadcast_timer.cancel(); + error_code ec; + m_broadcast_timer.cancel(ec); for (std::set::iterator i = m_devices.begin() , end(m_devices.end()); i != end; ++i) @@ -451,8 +521,10 @@ try // ask for it rootdevice& d = const_cast(*i); TORRENT_ASSERT(d.magic == 1337); +#ifndef BOOST_NO_EXCEPTIONS try { +#endif #ifdef TORRENT_UPNP_LOGGING m_log << time_now_string() << " ==> connecting to " << d.url << std::endl; @@ -461,7 +533,8 @@ try d.upnp_connection.reset(new http_connection(m_io_service , m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2 , boost::ref(d), _5))); - d.upnp_connection->get(d.url); + d.upnp_connection->get(d.url, seconds(30), 1); +#ifndef BOOST_NO_EXCEPTIONS } catch (std::exception& e) { @@ -473,16 +546,11 @@ try #endif d.disabled = true; } +#endif } } } } -#ifndef NDEBUG -catch (std::exception&) -{ - TORRENT_ASSERT(false); -}; -#endif void upnp::post(upnp::rootdevice const& d, std::string const& soap , std::string const& soap_action) @@ -509,6 +577,8 @@ void upnp::post(upnp::rootdevice const& d, std::string const& soap void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i) { + mutex_t::scoped_lock l(m_mutex); + TORRENT_ASSERT(d.magic == 1337); if (!d.upnp_connection) @@ -530,11 +600,12 @@ void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i) "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" ""; + error_code ec; soap << "" "" << d.mapping[i].external_port << "" - "" << (d.mapping[i].protocol ? "UDP" : "TCP") << "" + "" << (d.mapping[i].protocol == udp ? "UDP" : "TCP") << "" "" << d.mapping[i].local_port << "" - "" << c.socket().local_endpoint().address().to_string() << "" + "" << c.socket().local_endpoint(ec).address() << "" "1" "" << m_user_agent << "" "" << d.lease_duration << ""; @@ -543,22 +614,45 @@ void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i) post(d, soap.str(), soap_action); } -void upnp::map_port(rootdevice& d, int i) +void upnp::next(rootdevice& d, int i) +{ + if (i < num_mappings() - 1) + { + update_map(d, i + 1); + } + else + { + std::vector::iterator i + = std::find_if(d.mapping.begin(), d.mapping.end() + , boost::bind(&mapping_t::action, _1) != int(mapping_t::action_none)); + if (i == d.mapping.end()) return; + + update_map(d, i - d.mapping.begin()); + } +} + +void upnp::update_map(rootdevice& d, int i) { TORRENT_ASSERT(d.magic == 1337); + TORRENT_ASSERT(i < int(d.mapping.size())); + TORRENT_ASSERT(d.mapping.size() == m_mappings.size()); + if (d.upnp_connection) return; - if (!d.mapping[i].need_update) + mapping_t& m = d.mapping[i]; + + if (m.action == mapping_t::action_none + || m.protocol == none) { #ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() << " *** mapping (" << i - << ") does not need update, skipping" << std::endl; + if (m.protocol != none) + m_log << time_now_string() << " *** mapping (" << i + << ") does not need update, skipping" << std::endl; #endif - if (i < num_mappings - 1) - map_port(d, i + 1); + next(d, i); return; } - d.mapping[i].need_update = false; + TORRENT_ASSERT(!d.upnp_connection); TORRENT_ASSERT(d.service_namespace); @@ -566,18 +660,42 @@ void upnp::map_port(rootdevice& d, int i) m_log << time_now_string() << " ==> connecting to " << d.hostname << std::endl; #endif - if (d.upnp_connection) d.upnp_connection->close(); - d.upnp_connection.reset(new http_connection(m_io_service - , m_cc, bind(&upnp::on_upnp_map_response, self(), _1, _2 - , boost::ref(d), i, _5), true - , bind(&upnp::create_port_mapping, self(), _1, boost::ref(d), i))); + if (m.action == mapping_t::action_add) + { + if (m.failcount > 5) + { + // giving up + next(d, i); + return; + } - d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) - , seconds(10)); + if (d.upnp_connection) d.upnp_connection->close(); + d.upnp_connection.reset(new http_connection(m_io_service + , m_cc, bind(&upnp::on_upnp_map_response, self(), _1, _2 + , boost::ref(d), i, _5), true + , bind(&upnp::create_port_mapping, self(), _1, boost::ref(d), i))); + + d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) + , seconds(10), 1); + } + else if (m.action == mapping_t::action_delete) + { + if (d.upnp_connection) d.upnp_connection->close(); + d.upnp_connection.reset(new http_connection(m_io_service + , m_cc, bind(&upnp::on_upnp_unmap_response, self(), _1, _2 + , boost::ref(d), i, _5), true + , bind(&upnp::delete_port_mapping, self(), boost::ref(d), i))); + d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) + , seconds(10), 1); + } + + m.action = mapping_t::action_none; } void upnp::delete_port_mapping(rootdevice& d, int i) { + mutex_t::scoped_lock l(m_mutex); + TORRENT_ASSERT(d.magic == 1337); if (!d.upnp_connection) @@ -601,39 +719,12 @@ void upnp::delete_port_mapping(rootdevice& d, int i) soap << "" "" << d.mapping[i].external_port << "" - "" << (d.mapping[i].protocol ? "UDP" : "TCP") << ""; + "" << (d.mapping[i].protocol == udp ? "UDP" : "TCP") << ""; soap << ""; post(d, soap.str(), soap_action); } -// requires the mutex to be locked -void upnp::unmap_port(rootdevice& d, int i) -{ - TORRENT_ASSERT(d.magic == 1337); - if (d.mapping[i].external_port == 0 - || d.disabled) - { - if (i < num_mappings - 1) - { - unmap_port(d, i + 1); - } - return; - } -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> connecting to " << d.hostname << std::endl; -#endif - - if (d.upnp_connection) d.upnp_connection->close(); - d.upnp_connection.reset(new http_connection(m_io_service - , m_cc, bind(&upnp::on_upnp_unmap_response, self(), _1, _2 - , boost::ref(d), i, _5), true - , bind(&upnp::delete_port_mapping, self(), boost::ref(d), i))); - d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) - , seconds(10)); -} - namespace { struct parse_state @@ -650,6 +741,7 @@ namespace std::string top_tag; std::string control_url; char const* service_type; + std::string model; }; void find_control_url(int type, char const* string, parse_state& state) @@ -663,6 +755,10 @@ namespace { state.top_tag = string; } + else if (!strcmp(string, "modelName")) + { + state.top_tag = string; + } } else if (type == xml_end_tag) { @@ -686,15 +782,21 @@ namespace state.control_url = string; if (state.found_service) state.exit = true; } + else if (state.top_tag == "modelName") + { + state.model = string; + } } } } -void upnp::on_upnp_xml(asio::error_code const& e +void upnp::on_upnp_xml(error_code const& e , libtorrent::http_parser const& p, rootdevice& d - , http_connection& c) try + , http_connection& c) { + mutex_t::scoped_lock l(m_mutex); + TORRENT_ASSERT(d.magic == 1337); if (d.upnp_connection && d.upnp_connection.get() == &c) { @@ -740,6 +842,7 @@ void upnp::on_upnp_xml(asio::error_code const& e if (s.found_service) { d.service_namespace = s.service_type; + if (!s.model.empty()) m_model = s.model; } else { @@ -751,6 +854,7 @@ void upnp::on_upnp_xml(asio::error_code const& e if (s.found_service) { d.service_namespace = s.service_type; + if (!s.model.empty()) m_model = s.model; } else { @@ -772,19 +876,26 @@ void upnp::on_upnp_xml(asio::error_code const& e d.control_url = s.control_url; - map_port(d, 0); + if (num_mappings() > 0) update_map(d, 0); } -catch (std::exception&) -{ - disable(); -}; -void upnp::disable() +void upnp::disable(char const* msg) { m_disabled = true; + + // kill all mappings + for (std::vector::iterator i = m_mappings.begin() + , end(m_mappings.end()); i != end; ++i) + { + if (i->protocol == none) continue; + i->protocol = none; + m_callback(i - m_mappings.begin(), 0, msg); + } + m_devices.clear(); - m_broadcast_timer.cancel(); - m_refresh_timer.cancel(); + error_code ec; + m_broadcast_timer.cancel(ec); + m_refresh_timer.cancel(ec); m_socket.close(); } @@ -840,10 +951,12 @@ namespace } -void upnp::on_upnp_map_response(asio::error_code const& e +void upnp::on_upnp_map_response(error_code const& e , libtorrent::http_parser const& p, rootdevice& d, int mapping - , http_connection& c) try + , http_connection& c) { + mutex_t::scoped_lock l(m_mutex); + TORRENT_ASSERT(d.magic == 1337); if (d.upnp_connection && d.upnp_connection.get() == &c) { @@ -886,7 +999,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e m_log << time_now_string() << " <== error while adding portmap: incomplete http message" << std::endl; #endif - d.disabled = true; + next(d, mapping); return; } @@ -905,37 +1018,44 @@ void upnp::on_upnp_map_response(asio::error_code const& e } #endif + mapping_t& m = d.mapping[mapping]; + if (s.error_code == 725) { // only permanent leases supported d.lease_duration = 0; - d.mapping[mapping].need_update = true; - map_port(d, mapping); + m.action = mapping_t::action_add; + ++m.failcount; + update_map(d, mapping); return; } - else if (s.error_code == 718) + else if (s.error_code == 718 || s.error_code == 727) { - // conflict in mapping, try next external port - ++d.mapping[mapping].external_port; - d.mapping[mapping].need_update = true; - map_port(d, mapping); + if (m.external_port != 0) + { + // conflict in mapping, set port to wildcard + // and let the router decide + m.external_port = 0; + m.action = mapping_t::action_add; + ++m.failcount; + update_map(d, mapping); + return; + } + return_error(mapping, s.error_code); + } + else if (s.error_code == 716) + { + // The external port cannot be wildcarder + // pick a random port + m.external_port = 40000 + (rand() % 10000); + m.action = mapping_t::action_add; + ++m.failcount; + update_map(d, mapping); return; } else if (s.error_code != -1) { - int num_errors = sizeof(error_codes) / sizeof(error_codes[0]); - error_code_t* end = error_codes + num_errors; - error_code_t tmp = {s.error_code, 0}; - error_code_t* e = std::lower_bound(error_codes, end, tmp - , bind(&error_code_t::code, _1) < bind(&error_code_t::code, _2)); - std::string error_string = "UPnP mapping error "; - error_string += boost::lexical_cast(s.error_code); - if (e != end && e->code == s.error_code) - { - error_string += ": "; - error_string += e->msg; - } - m_callback(0, 0, error_string); + return_error(mapping, s.error_code); } #ifdef TORRENT_UPNP_LOGGING @@ -946,51 +1066,53 @@ void upnp::on_upnp_map_response(asio::error_code const& e if (s.error_code == -1) { - int tcp = 0; - int udp = 0; - - if (mapping == 0) - tcp = d.mapping[mapping].external_port; - else - udp = d.mapping[mapping].external_port; - - m_callback(tcp, udp, ""); + m_callback(mapping, m.external_port, ""); if (d.lease_duration > 0) { - d.mapping[mapping].expires = time_now() + m.expires = time_now() + seconds(int(d.lease_duration * 0.75f)); ptime next_expire = m_refresh_timer.expires_at(); if (next_expire < time_now() - || next_expire > d.mapping[mapping].expires) + || next_expire > m.expires) { - m_refresh_timer.expires_at(d.mapping[mapping].expires); + error_code ec; + m_refresh_timer.expires_at(m.expires, ec); m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1)); } } else { - d.mapping[mapping].expires = max_time(); + m.expires = max_time(); } + m.failcount = 0; } - for (int i = 0; i < num_mappings; ++i) - { - if (d.mapping[i].need_update) - { - map_port(d, i); - return; - } - } + next(d, mapping); } -catch (std::exception&) -{ - disable(); -}; -void upnp::on_upnp_unmap_response(asio::error_code const& e - , libtorrent::http_parser const& p, rootdevice& d, int mapping - , http_connection& c) try +void upnp::return_error(int mapping, int code) { + int num_errors = sizeof(error_codes) / sizeof(error_codes[0]); + error_code_t* end = error_codes + num_errors; + error_code_t tmp = {code, 0}; + error_code_t* e = std::lower_bound(error_codes, end, tmp + , bind(&error_code_t::code, _1) < bind(&error_code_t::code, _2)); + std::string error_string = "UPnP mapping error "; + error_string += boost::lexical_cast(code); + if (e != end && e->code == code) + { + error_string += ": "; + error_string += e->msg; + } + m_callback(mapping, 0, error_string); +} + +void upnp::on_upnp_unmap_response(error_code const& e + , libtorrent::http_parser const& p, rootdevice& d, int mapping + , http_connection& c) +{ + mutex_t::scoped_lock l(m_mutex); + TORRENT_ASSERT(d.magic == 1337); if (d.upnp_connection && d.upnp_connection.get() == &c) { @@ -1004,58 +1126,50 @@ void upnp::on_upnp_unmap_response(asio::error_code const& e m_log << time_now_string() << " <== error while deleting portmap: " << e.message() << std::endl; #endif - } - - if (!p.header_finished()) + } else if (!p.header_finished()) { #ifdef TORRENT_UPNP_LOGGING m_log << time_now_string() << " <== error while deleting portmap: incomplete http message" << std::endl; #endif - return; } - - if (p.status_code() != 200) + else if (p.status_code() != 200) { #ifdef TORRENT_UPNP_LOGGING m_log << time_now_string() << " <== error while deleting portmap: " << p.message() << std::endl; #endif - d.disabled = true; - return; } + else + { #ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== unmap response: " << std::string(p.get_body().begin, p.get_body().end) - << std::endl; + m_log << time_now_string() + << " <== unmap response: " << std::string(p.get_body().begin, p.get_body().end) + << std::endl; #endif - - // ignore errors and continue with the next mapping for this device - if (mapping < num_mappings - 1) - { - unmap_port(d, mapping + 1); - return; } -} -catch (std::exception&) -{ - disable(); -}; -void upnp::on_expire(asio::error_code const& e) try + d.mapping[mapping].protocol = none; + + next(d, mapping); +} + +void upnp::on_expire(error_code const& e) { if (e) return; ptime now = time_now(); ptime next_expire = max_time(); + mutex_t::scoped_lock l(m_mutex); + for (std::set::iterator i = m_devices.begin() , end(m_devices.end()); i != end; ++i) { rootdevice& d = const_cast(*i); TORRENT_ASSERT(d.magic == 1337); - for (int m = 0; m < num_mappings; ++m) + for (int m = 0; m < num_mappings(); ++m) { if (d.mapping[m].expires != max_time()) continue; @@ -1063,7 +1177,7 @@ void upnp::on_expire(asio::error_code const& e) try if (d.mapping[m].expires < now) { d.mapping[m].expires = max_time(); - map_port(d, m); + update_map(d, m); } else if (d.mapping[m].expires < next_expire) { @@ -1073,35 +1187,41 @@ void upnp::on_expire(asio::error_code const& e) try } if (next_expire != max_time()) { - m_refresh_timer.expires_at(next_expire); + error_code ec; + m_refresh_timer.expires_at(next_expire, ec); m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1)); } } -catch (std::exception&) -{ - disable(); -}; void upnp::close() { - m_refresh_timer.cancel(); - m_broadcast_timer.cancel(); + mutex_t::scoped_lock l(m_mutex); + + error_code ec; + m_refresh_timer.cancel(ec); + m_broadcast_timer.cancel(ec); m_closing = true; m_socket.close(); - if (m_disabled) - { - m_devices.clear(); - return; - } - for (std::set::iterator i = m_devices.begin() , end(m_devices.end()); i != end; ++i) { rootdevice& d = const_cast(*i); TORRENT_ASSERT(d.magic == 1337); if (d.control_url.empty()) continue; - unmap_port(d, 0); + for (std::vector::iterator j = d.mapping.begin() + , end(d.mapping.end()); j != end; ++j) + { + if (j->protocol == none) continue; + if (j->action == mapping_t::action_add) + { + j->action = mapping_t::action_none; + continue; + } + j->action = mapping_t::action_delete; + m_mappings[j - d.mapping.begin()].protocol = none; + } + if (num_mappings() > 0) update_map(d, 0); } } diff --git a/libtorrent/src/ut_metadata.cpp b/libtorrent/src/ut_metadata.cpp new file mode 100644 index 000000000..848c3795d --- /dev/null +++ b/libtorrent/src/ut_metadata.cpp @@ -0,0 +1,459 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +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. + +*/ + +#include "libtorrent/pch.hpp" + +#ifdef _MSC_VER +#pragma warning(push, 1) +#endif + +#include +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include +#include +#include +#include + +#include "libtorrent/peer_connection.hpp" +#include "libtorrent/bt_peer_connection.hpp" +#include "libtorrent/hasher.hpp" +#include "libtorrent/bencode.hpp" +#include "libtorrent/torrent.hpp" +#include "libtorrent/extensions.hpp" +#include "libtorrent/extensions/ut_metadata.hpp" +#include "libtorrent/alert_types.hpp" +#ifdef TORRENT_STATS +#include "libtorrent/aux_/session_impl.hpp" +#endif + +namespace libtorrent { namespace +{ + int div_round_up(int numerator, int denominator) + { + return (numerator + denominator - 1) / denominator; + } + + void nop(char*) {} + + struct ut_metadata_plugin : torrent_plugin + { + ut_metadata_plugin(torrent& t) + : m_torrent(t) + , m_metadata_progress(0) + , m_metadata_size(0) + { + } + + virtual void on_files_checked() + { + // if the torrent is a seed, copy the metadata from + // the torrent before it is deallocated + if (m_torrent.is_seed()) + metadata(); + } + + virtual boost::shared_ptr new_connection( + peer_connection* pc); + + buffer::const_interval metadata() const + { + TORRENT_ASSERT(m_torrent.valid_metadata()); + if (!m_metadata) + { + m_metadata = m_torrent.torrent_file().metadata(); + m_metadata_size = m_torrent.torrent_file().metadata_size(); + TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final() + == m_torrent.torrent_file().info_hash()); + } + return buffer::const_interval(m_metadata.get(), m_metadata.get() + + m_metadata_size); + } + + bool received_metadata(char const* buf, int size, int piece, int total_size) + { + if (m_torrent.valid_metadata()) return false; + + if (!m_metadata) + { + // verify the total_size + if (total_size <= 0 || total_size > 500 * 1024) return false; + + m_metadata.reset(new char[total_size]); + m_requested_metadata.resize(div_round_up(total_size, 16 * 1024), 0); + m_metadata_size = total_size; + } + + if (piece < 0 || piece >= int(m_requested_metadata.size())) + return false; + + TORRENT_ASSERT(piece * 16 * 1024 + size <= m_metadata_size); + std::memcpy(&m_metadata[piece * 16 * 1024], buf, size); + // mark this piece has 'have' + m_requested_metadata[piece] = (std::numeric_limits::max)(); + + bool have_all = std::count(m_requested_metadata.begin() + , m_requested_metadata.end(), (std::numeric_limits::max)()) + == int(m_requested_metadata.size()); + + if (!have_all) return false; + + hasher h; + h.update(&m_metadata[0], m_metadata_size); + sha1_hash info_hash = h.final(); + + if (info_hash != m_torrent.torrent_file().info_hash()) + { + std::fill(m_requested_metadata.begin(), m_requested_metadata.end(), 0); + + if (m_torrent.alerts().should_post()) + { + m_torrent.alerts().post_alert(metadata_failed_alert( + m_torrent.get_handle())); + } + + return false; + } + + lazy_entry metadata; + int ret = lazy_bdecode(m_metadata.get(), m_metadata.get() + m_metadata_size, metadata); + std::string error; + if (!m_torrent.set_metadata(metadata, error)) + { + // this means the metadata is correct, since we + // verified it against the info-hash, but we + // failed to parse it. Pause the torrent + // TODO: Post an alert! + m_torrent.pause(); + return false; + } + + // clear the storage for the bitfield + std::vector().swap(m_requested_metadata); + + return true; + } + + // returns a piece of the metadata that + // we should request. + int metadata_request(); + + // this is called from the peer_connection for + // each piece of metadata it receives + void metadata_progress(int total_size, int received) + { + m_metadata_progress += received; + m_metadata_size = total_size; + } + + void on_piece_pass(int) + { + // if we became a seed, copy the metadata from + // the torrent before it is deallocated + if (m_torrent.is_seed()) + metadata(); + } + + void metadata_size(int size) + { + if (m_metadata_size > 0 || size <= 0 || size > 500 * 1024) return; + m_metadata_size = size; + m_metadata.reset(new char[size]); + m_requested_metadata.resize(div_round_up(size, 16 * 1024), 0); + } + + private: + torrent& m_torrent; + + // this buffer is filled with the info-section of + // the metadata file while downloading it from + // peers, and while sending it. + // it is mutable because it's generated lazily + mutable boost::shared_array m_metadata; + + int m_metadata_progress; + mutable int m_metadata_size; + + // this vector keeps track of how many times each meatdata + // block has been requested + // std::numeric_limits::max() means we have the piece + std::vector m_requested_metadata; + }; + + + struct ut_metadata_peer_plugin : peer_plugin + { + ut_metadata_peer_plugin(torrent& t, bt_peer_connection& pc + , ut_metadata_plugin& tp) + : m_message_index(0) + , m_no_metadata(min_time()) + , m_torrent(t) + , m_pc(pc) + , m_tp(tp) + {} + + // can add entries to the extension handshake + virtual void add_handshake(entry& h) + { + entry& messages = h["m"]; + messages["ut_metadata"] = 15; + if (m_torrent.valid_metadata()) + h["metadata_size"] = m_tp.metadata().left(); + } + + // called when the extension handshake from the other end is received + virtual bool on_extension_handshake(lazy_entry const& h) + { + m_message_index = 0; + if (h.type() != lazy_entry::dict_t) return false; + lazy_entry const* messages = h.dict_find("m"); + if (!messages || messages->type() != lazy_entry::dict_t) return false; + + int index = messages->dict_find_int_value("ut_metadata", -1); + if (index == -1) return false; + m_message_index = index; + + int metadata_size = h.dict_find_int_value("metadata_size"); + if (metadata_size > 0) + m_tp.metadata_size(metadata_size); + return true; + } + + void write_metadata_packet(int type, int piece) + { + TORRENT_ASSERT(type >= 0 && type <= 2); + TORRENT_ASSERT(piece >= 0); + TORRENT_ASSERT(!m_pc.associated_torrent().expired()); + +#ifdef TORRENT_VERBOSE_LOGGING + (*m_pc.m_logger) << time_now_string() << " ==> UT_METADATA [ " + "type: " << type << " | piece: " << piece << " ]\n"; +#endif + // abort if the peer doesn't support the metadata extension + if (m_message_index == 0) return; + + entry e; + e["msg_type"] = type; + e["piece"] = piece; + + char const* metadata = 0; + int metadata_piece_size = 0; + + if (type == 1) + { + TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata()); + e["total_size"] = m_tp.metadata().left(); + int offset = piece * 16 * 1024; + metadata = m_tp.metadata().begin + offset; + metadata_piece_size = (std::min)( + int(m_tp.metadata().left() - offset), 16 * 1024); + TORRENT_ASSERT(metadata_piece_size > 0); + TORRENT_ASSERT(offset >= 0); + TORRENT_ASSERT(offset + metadata_piece_size <= int(m_tp.metadata().left())); + } + + char msg[200]; + char* header = msg; + char* p = &msg[6]; + int len = bencode(p, e); + int total_size = 2 + len + metadata_piece_size; + namespace io = detail; + io::write_uint32(total_size, header); + io::write_uint8(bt_peer_connection::msg_extended, header); + io::write_uint8(m_message_index, header); + + m_pc.send_buffer(msg, len + 6); + if (metadata_piece_size) m_pc.append_send_buffer( + (char*)metadata, metadata_piece_size, &nop); + } + + virtual bool on_extended(int length + , int extended_msg, buffer::const_interval body) + { + if (extended_msg != 15) return false; + if (m_message_index == 0) return false; + + if (length > 17 * 1024) + { + m_pc.disconnect("ut_metadata message larger than 17 kB", 2); + return true; + } + + if (!m_pc.packet_finished()) return true; + + int len; + entry msg = bdecode(body.begin, body.end, len); + if (msg.type() == entry::undefined_t) + { + m_pc.disconnect("invalid bencoding in ut_metadata message", 2); + return true; + } + + int type = msg["msg_type"].integer(); + int piece = msg["piece"].integer(); + +#ifdef TORRENT_VERBOSE_LOGGING + (*m_pc.m_logger) << time_now_string() << " <== UT_METADATA [ " + "type: " << type << " | piece: " << piece << " ]\n"; +#endif + + switch (type) + { + case 0: // request + { + if (!m_torrent.valid_metadata()) + { + write_metadata_packet(2, piece); + return true; + } + // TODO: put the request on the queue in some cases + write_metadata_packet(1, piece); + } + break; + case 1: // data + { + std::vector::iterator i = std::find(m_sent_requests.begin() + , m_sent_requests.end(), piece); + + // unwanted piece? + if (i == m_sent_requests.end()) return true; + + m_sent_requests.erase(i); + entry const* total_size = msg.find_key("total_size"); + m_tp.received_metadata(body.begin + len, body.left() - len, piece + , (total_size && total_size->type() == entry::int_t) ? total_size->integer() : 0); + } + break; + case 2: // have no data + { + m_no_metadata = time_now(); + std::vector::iterator i = std::find(m_sent_requests.begin() + , m_sent_requests.end(), piece); + // unwanted piece? + if (i == m_sent_requests.end()) return true; + m_sent_requests.erase(i); + } + break; + default: + { + std::stringstream msg; + msg << "unknown ut_metadata extension message: " << type; + m_pc.disconnect(msg.str().c_str(), 2); + } + } + return true; + } + + virtual void tick() + { + // if we don't have any metadata, and this peer + // supports the request metadata extension + // and we aren't currently waiting for a request + // reply. Then, send a request for some metadata. + if (!m_torrent.valid_metadata() + && m_message_index != 0 + && m_sent_requests.size() < 2 + && has_metadata()) + { + int piece = m_tp.metadata_request(); + m_sent_requests.push_back(piece); + write_metadata_packet(0, piece); + } + } + + bool has_metadata() const + { + return time_now() - m_no_metadata > minutes(1); + } + + private: + + // this is the message index the remote peer uses + // for metadata extension messages. + int m_message_index; + + // this is set to the current time each time we get a + // "I don't have metadata" message. + ptime m_no_metadata; + + // request queues + std::vector m_sent_requests; + std::vector m_incoming_requests; + + torrent& m_torrent; + bt_peer_connection& m_pc; + ut_metadata_plugin& m_tp; + }; + + boost::shared_ptr ut_metadata_plugin::new_connection( + peer_connection* pc) + { + bt_peer_connection* c = dynamic_cast(pc); + if (!c) return boost::shared_ptr(); + return boost::shared_ptr(new ut_metadata_peer_plugin(m_torrent, *c, *this)); + } + + int ut_metadata_plugin::metadata_request() + { + std::vector::iterator i = std::min_element( + m_requested_metadata.begin(), m_requested_metadata.end()); + + if (m_requested_metadata.empty()) + { + // if we don't know how many pieces there are + // just ask for piece 0 + m_requested_metadata.resize(1, 1); + return 0; + } + + int piece = i - m_requested_metadata.begin(); + m_requested_metadata[piece] = piece; + return piece; + } + +} } + +namespace libtorrent +{ + + boost::shared_ptr create_ut_metadata_plugin(torrent* t, void*) + { + return boost::shared_ptr(new ut_metadata_plugin(*t)); + } + +} + + diff --git a/libtorrent/src/ut_pex.cpp b/libtorrent/src/ut_pex.cpp index 18c37cda4..723f119d2 100644 --- a/libtorrent/src/ut_pex.cpp +++ b/libtorrent/src/ut_pex.cpp @@ -196,20 +196,17 @@ namespace libtorrent { namespace messages[extension_name] = extension_index; } - virtual bool on_extension_handshake(entry const& h) + virtual bool on_extension_handshake(lazy_entry const& h) { - entry const& messages = h["m"]; + m_message_index = 0; + if (h.type() != lazy_entry::dict_t) return false; + lazy_entry const* messages = h.dict_find("m"); + if (!messages || messages->type() != lazy_entry::dict_t) return false; - if (entry const* index = messages.find_key(extension_name)) - { - m_message_index = int(index->integer()); - return true; - } - else - { - m_message_index = 0; - return false; - } + int index = messages->dict_find_int_value(extension_name, -1); + if (index == -1) return false; + m_message_index = index; + return true; } virtual bool on_extended(int length, int msg, buffer::const_interval body) @@ -218,57 +215,64 @@ namespace libtorrent { namespace if (m_message_index == 0) return false; if (length > 500 * 1024) - throw protocol_error("uT peer exchange message larger than 500 kB"); + { + m_pc.disconnect("peer exchange message larger than 500 kB", 2); + return true; + } if (body.left() < length) return true; - try + lazy_entry pex_msg; + int ret = lazy_bdecode(body.begin, body.end, pex_msg); + if (pex_msg.type() != lazy_entry::dict_t) { - entry pex_msg = bdecode(body.begin, body.end); - std::string const& peers = pex_msg["added"].string(); - std::string const& peer_flags = pex_msg["added.f"].string(); + m_pc.disconnect("invalid bencoding in ut_metadata message", 2); + return true; + } - int num_peers = peers.length() / 6; - char const* in = peers.c_str(); - char const* fin = peer_flags.c_str(); + lazy_entry const* p = pex_msg.dict_find("added"); + lazy_entry const* pf = pex_msg.dict_find("added.f"); - if (int(peer_flags.size()) != num_peers) - return true; + if (p != 0 + && pf != 0 + && p->type() == lazy_entry::string_t + && pf->type() == lazy_entry::string_t + && pf->string_length() == p->string_length() / 6) + { + int num_peers = pf->string_length(); + char const* in = p->string_ptr(); + char const* fin = pf->string_ptr(); peer_id pid(0); policy& p = m_torrent.get_policy(); for (int i = 0; i < num_peers; ++i) { tcp::endpoint adr = detail::read_v4_endpoint(in); - char flags = detail::read_uint8(fin); + char flags = *fin++; p.peer_from_tracker(adr, pid, peer_info::pex, flags); } - - if (entry const* p6 = pex_msg.find_key("added6")) - { - std::string const& peers6 = p6->string(); - std::string const& peer6_flags = pex_msg["added6.f"].string(); - - int num_peers = peers6.length() / 18; - char const* in = peers6.c_str(); - char const* fin = peer6_flags.c_str(); - - if (int(peer6_flags.size()) != num_peers) - return true; - - peer_id pid(0); - policy& p = m_torrent.get_policy(); - for (int i = 0; i < num_peers; ++i) - { - tcp::endpoint adr = detail::read_v6_endpoint(in); - char flags = detail::read_uint8(fin); - p.peer_from_tracker(adr, pid, peer_info::pex, flags); - } - } } - catch (std::exception&) + + lazy_entry const* p6 = pex_msg.dict_find("added6"); + lazy_entry const* p6f = pex_msg.dict_find("added6.f"); + if (p6 != 0 + && p6f != 0 + && p6->type() == lazy_entry::string_t + && p6f->type() == lazy_entry::string_t + && p6f->string_length() == p6->string_length() / 18) { - throw protocol_error("invalid uT peer exchange message"); + int num_peers = p6f->string_length(); + char const* in = p6->string_ptr(); + char const* fin = p6f->string_ptr(); + + peer_id pid(0); + policy& p = m_torrent.get_policy(); + for (int i = 0; i < num_peers; ++i) + { + tcp::endpoint adr = detail::read_v6_endpoint(in); + char flags = *fin++; + p.peer_from_tracker(adr, pid, peer_info::pex, flags); + } } return true; } diff --git a/libtorrent/src/web_peer_connection.cpp b/libtorrent/src/web_peer_connection.cpp index 71b4b1082..ab3b0bf64 100755 --- a/libtorrent/src/web_peer_connection.cpp +++ b/libtorrent/src/web_peer_connection.cpp @@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/io.hpp" #include "libtorrent/version.hpp" #include "libtorrent/aux_/session_impl.hpp" +#include "libtorrent/parse_url.hpp" using boost::bind; using boost::shared_ptr; @@ -73,6 +74,8 @@ namespace libtorrent // we want large blocks as well, so // we can request more bytes at once request_large_blocks(true); + set_upload_only(true); + // we only want left-over bandwidth set_priority(0); shared_ptr tor = t.lock(); @@ -96,8 +99,10 @@ namespace libtorrent #endif std::string protocol; - boost::tie(protocol, m_auth, m_host, m_port, m_path) + char const* error; + boost::tie(protocol, m_auth, m_host, m_port, m_path, error) = parse_url_components(url); + TORRENT_ASSERT(error == 0); if (!m_auth.empty()) m_auth = base64encode(m_auth); @@ -152,8 +157,8 @@ namespace libtorrent TORRENT_ASSERT(t); // this is always a seed - incoming_bitfield(std::vector( - t->torrent_file().num_pieces(), true)); + incoming_have_all(); + // it is always possible to request pieces incoming_unchoke(); @@ -238,7 +243,7 @@ namespace libtorrent } else { - std::vector files = info.map_block(r.piece, r.start + std::vector files = info.files().map_block(r.piece, r.start , r.length); for (std::vector::iterator i = files.begin(); @@ -250,13 +255,13 @@ namespace libtorrent if (using_proxy) { request += m_url; - std::string path = info.file_at(f.file_index).path.string(); + std::string path = info.files().at(f.file_index).path.string(); request += escape_path(path.c_str(), path.length()); } else { std::string path = m_path; - path += info.file_at(f.file_index).path.string(); + path += info.files().at(f.file_index).path.string(); request += escape_path(path.c_str(), path.length()); } request += " HTTP/1.1\r\n"; @@ -298,7 +303,7 @@ namespace libtorrent (*m_logger) << request << "\n"; #endif - send_buffer(request.c_str(), request.size()); + send_buffer(request.c_str(), request.size(), message_type_request); } // -------------------------- @@ -316,8 +321,7 @@ namespace libtorrent } } - // throws exception when the client should be disconnected - void web_peer_connection::on_receive(asio::error_code const& error + void web_peer_connection::on_receive(error_code const& error , std::size_t bytes_transferred) { INVARIANT_CHECK; @@ -345,10 +349,17 @@ namespace libtorrent bool header_finished = m_parser.header_finished(); if (!header_finished) { - boost::tie(payload, protocol) = m_parser.incoming(recv_buffer); + bool error = false; + boost::tie(payload, protocol) = m_parser.incoming(recv_buffer, error); m_statistics.received_bytes(0, protocol); bytes_transferred -= protocol; + if (error) + { + disconnect("failed to parse HTTP response", 2); + return; + } + TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H'); TORRENT_ASSERT(recv_buffer.left() <= packet_size()); @@ -375,13 +386,14 @@ namespace libtorrent t->remove_url_seed(m_url); std::string error_msg = boost::lexical_cast(m_parser.status_code()) + " " + m_parser.message(); - if (m_ses.m_alerts.should_post(alert::warning)) + if (m_ses.m_alerts.should_post()) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url() , error_msg)); } - throw std::runtime_error(error_msg); + disconnect(error_msg.c_str(), 1); + return; } if (!m_parser.header_finished()) { @@ -407,7 +419,8 @@ namespace libtorrent { // we should not try this server again. t->remove_url_seed(m_url); - throw std::runtime_error("got HTTP redirection status without location header"); + disconnect("got HTTP redirection status without location header", 2); + return; } bool single_file_request = false; @@ -421,20 +434,26 @@ namespace libtorrent int file_index = m_file_requests.front(); torrent_info const& info = t->torrent_file(); - std::string path = info.file_at(file_index).path.string(); + std::string path = info.files().at(file_index).path.string(); path = escape_path(path.c_str(), path.length()); size_t i = location.rfind(path); if (i == std::string::npos) { t->remove_url_seed(m_url); - throw std::runtime_error("got invalid HTTP redirection location (\"" + location + "\") " - "expected it to end with: " + path); + std::stringstream msg; + msg << "got invalid HTTP redirection location (\"" << location << "\") " + "expected it to end with: " << path; + disconnect(msg.str().c_str(), 2); + return; } location.resize(i); } t->add_url_seed(location); t->remove_url_seed(m_url); - throw std::runtime_error("redirecting to " + location); + std::stringstream msg; + msg << "redirecting to \"" << location << "\""; + disconnect(msg.str().c_str()); + return; } std::string const& server_version = m_parser.header("server"); @@ -469,7 +488,10 @@ namespace libtorrent { // we should not try this server again. t->remove_url_seed(m_url); - throw std::runtime_error("invalid range in HTTP response: " + range_str.str()); + std::stringstream msg; + msg << "invalid range in HTTP response: " << range_str.str(); + disconnect(msg.str().c_str(), 2); + return; } // the http range is inclusive range_end++; @@ -482,7 +504,8 @@ namespace libtorrent { // we should not try this server again. t->remove_url_seed(m_url); - throw std::runtime_error("no content-length in HTTP response"); + disconnect("no content-length in HTTP response", 2); + return; } } @@ -499,10 +522,13 @@ namespace libtorrent torrent_info const& info = t->torrent_file(); if (m_requests.empty() || m_file_requests.empty()) - throw std::runtime_error("unexpected HTTP response"); + { + disconnect("unexpected HTTP response", 2); + return; + } int file_index = m_file_requests.front(); - peer_request in_range = info.map_file(file_index, range_start + peer_request in_range = info.files().map_file(file_index, range_start , int(range_end - range_start)); peer_request front_request = m_requests.front(); @@ -530,7 +556,8 @@ namespace libtorrent { // this means the end of the incoming request ends _before_ the // first expected byte (fs + m_piece.size()) - throw std::runtime_error("invalid range in HTTP response"); + disconnect("invalid range in HTTP response", 2); + return; } // if the request is contained in the range (i.e. the entire request @@ -658,7 +685,7 @@ namespace libtorrent } // throws exception when the client should be disconnected - void web_peer_connection::on_sent(asio::error_code const& error + void web_peer_connection::on_sent(error_code const& error , std::size_t bytes_transferred) { INVARIANT_CHECK; diff --git a/msgfmt.py b/msgfmt.py index 8efa400f5..31d117d9c 100644 --- a/msgfmt.py +++ b/msgfmt.py @@ -1,219 +1,438 @@ -# -*- coding: iso-8859-1 -*- -# Written by Martin v. Lwis -# Plural forms support added by alexander smishlajev -""" -Generate binary message catalog from textual translation description. - -This program converts a textual Uniforum-style message catalog (.po file) into -a binary GNU catalog (.mo file). This is essentially the same function as the -GNU msgfmt program, however, it is a simpler implementation. - -Usage: msgfmt.py [OPTIONS] filename.po - -Options: - -o file - --output-file=file - Specify the output file to write to. If omitted, output will go to a - file named filename.mo (based off the input file name). - - -h - --help - Print this message and exit. - - -V - --version - Display version information and exit. -""" - -import sys -import os -import getopt -import struct -import array - -__version__ = "1.1" - -MESSAGES = {} - - -def usage (ecode, msg=''): - """ - Print usage and msg and exit with given code. - """ - print >> sys.stderr, __doc__ - if msg: - print >> sys.stderr, msg - sys.exit(ecode) - - -def add (msgid, transtr, fuzzy): - """ - Add a non-fuzzy translation to the dictionary. - """ - global MESSAGES - if not fuzzy and transtr and not transtr.startswith('\0'): - MESSAGES[msgid] = transtr - - -def generate (): - """ - Return the generated output. - """ - global MESSAGES - keys = MESSAGES.keys() - # the keys are sorted in the .mo file - keys.sort() - offsets = [] - ids = strs = '' - for _id in keys: - # For each string, we need size and file offset. Each string is NUL - # terminated; the NUL does not count into the size. - offsets.append((len(ids), len(_id), len(strs), len(MESSAGES[_id]))) - ids += _id + '\0' - strs += MESSAGES[_id] + '\0' - output = '' - # The header is 7 32-bit unsigned integers. We don't use hash tables, so - # the keys start right after the index tables. - # translated string. - keystart = 7*4+16*len(keys) - # and the values start after the keys - valuestart = keystart + len(ids) - koffsets = [] - voffsets = [] - # The string table first has the list of keys, then the list of values. - # Each entry has first the size of the string, then the file offset. - for o1, l1, o2, l2 in offsets: - koffsets += [l1, o1+keystart] - voffsets += [l2, o2+valuestart] - offsets = koffsets + voffsets - output = struct.pack("Iiiiiii", - 0x950412deL, # Magic - 0, # Version - len(keys), # # of entries - 7*4, # start of key index - 7*4+len(keys)*8, # start of value index - 0, 0) # size and offset of hash table - output += array.array("i", offsets).tostring() - output += ids - output += strs - return output - - -def make (filename, outfile): - ID = 1 - STR = 2 - global MESSAGES - MESSAGES = {} - - # Compute .mo name from .po name and arguments - if filename.endswith('.po'): - infile = filename - else: - infile = filename + '.po' - if outfile is None: - outfile = os.path.splitext(infile)[0] + '.mo' - - try: - lines = open(infile).readlines() - except IOError, msg: - print >> sys.stderr, msg - sys.exit(1) - - section = None - fuzzy = 0 - - # Parse the catalog - msgid = msgstr = '' - lno = 0 - for l in lines: - lno += 1 - # If we get a comment line after a msgstr, this is a new entry - if l[0] == '#' and section == STR: - add(msgid, msgstr, fuzzy) - section = None - fuzzy = 0 - # Record a fuzzy mark - if l[:2] == '#,' and (l.find('fuzzy') >= 0): - fuzzy = 1 - # Skip comments - if l[0] == '#': - continue - # Start of msgid_plural section, separate from singular form with \0 - if l.startswith('msgid_plural'): - msgid += '\0' - l = l[12:] - # Now we are in a msgid section, output previous section - elif l.startswith('msgid'): - if section == STR: - add(msgid, msgstr, fuzzy) - section = ID - l = l[5:] - msgid = msgstr = '' - # Now we are in a msgstr section - elif l.startswith('msgstr'): - section = STR - l = l[6:] - # Check for plural forms - if l.startswith('['): - # Separate plural forms with \0 - if not l.startswith('[0]'): - msgstr += '\0' - # Ignore the index - must come in sequence - l = l[l.index(']') + 1:] - # Skip empty lines - l = l.strip() - if not l: - continue - # XXX: Does this always follow Python escape semantics? - l = eval(l) - if section == ID: - msgid += l - elif section == STR: - msgstr += l - else: - print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \ - 'before:' - print >> sys.stderr, l - sys.exit(1) - # Add last entry - if section == STR: - add(msgid, msgstr, fuzzy) - - # Compute output - output = generate() - - try: - open(outfile,"wb").write(output) - except IOError,msg: - print >> sys.stderr, msg - - -def main (): - try: - opts, args = getopt.getopt(sys.argv[1:], 'hVo:', - ['help', 'version', 'output-file=']) - except getopt.error, msg: - usage(1, msg) - - outfile = None - # parse options - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-V', '--version'): - print >> sys.stderr, "msgfmt.py", __version__ - sys.exit(0) - elif opt in ('-o', '--output-file'): - outfile = arg - # do it - if not args: - print >> sys.stderr, 'No input file given' - print >> sys.stderr, "Try `msgfmt --help' for more information." - return - - for filename in args: - make(filename, outfile) - - -if __name__ == '__main__': +# -*- coding: iso-8859-1 -*- +# Written by Martin v. Lwis +# Plural forms support added by alexander smishlajev +""" +Generate binary message catalog from textual translation description. + +This program converts a textual Uniforum-style message catalog (.po file) into +a binary GNU catalog (.mo file). This is essentially the same function as the +GNU msgfmt program, however, it is a simpler implementation. + +Usage: msgfmt.py [OPTIONS] filename.po + +Options: + -o file + --output-file=file + Specify the output file to write to. If omitted, output will go to a + file named filename.mo (based off the input file name). + + -h + --help + Print this message and exit. + + -V + --version + Display version information and exit. +""" + +import sys +import os +import getopt +import struct +import array + +__version__ = "1.1" + +MESSAGES = {} + + +def usage (ecode, msg=''): + """ + Print usage and msg and exit with given code. + """ + print >> sys.stderr, __doc__ + if msg: + print >> sys.stderr, msg + sys.exit(ecode) + + +def add (msgid, transtr, fuzzy): + """ + Add a non-fuzzy translation to the dictionary. + """ + global MESSAGES + if not fuzzy and transtr and not transtr.startswith('\0'): + MESSAGES[msgid] = transtr + + +def generate (): + """ + Return the generated output. + """ + global MESSAGES + keys = MESSAGES.keys() + # the keys are sorted in the .mo file + keys.sort() + offsets = [] + ids = strs = '' + for _id in keys: + # For each string, we need size and file offset. Each string is NUL + # terminated; the NUL does not count into the size. + offsets.append((len(ids), len(_id), len(strs), len(MESSAGES[_id]))) + ids += _id + '\0' + strs += MESSAGES[_id] + '\0' + output = '' + # The header is 7 32-bit unsigned integers. We don't use hash tables, so + # the keys start right after the index tables. + # translated string. + keystart = 7*4+16*len(keys) + # and the values start after the keys + valuestart = keystart + len(ids) + koffsets = [] + voffsets = [] + # The string table first has the list of keys, then the list of values. + # Each entry has first the size of the string, then the file offset. + for o1, l1, o2, l2 in offsets: + koffsets += [l1, o1+keystart] + voffsets += [l2, o2+valuestart] + offsets = koffsets + voffsets + output = struct.pack("Iiiiiii", + 0x950412deL, # Magic + 0, # Version + len(keys), # # of entries + 7*4, # start of key index + 7*4+len(keys)*8, # start of value index + 0, 0) # size and offset of hash table + output += array.array("i", offsets).tostring() + output += ids + output += strs + return output + + +def make (filename, outfile): + ID = 1 + STR = 2 + global MESSAGES + MESSAGES = {} + + # Compute .mo name from .po name and arguments + if filename.endswith('.po'): + infile = filename + else: + infile = filename + '.po' + if outfile is None: + outfile = os.path.splitext(infile)[0] + '.mo' + + try: + lines = open(infile).readlines() + except IOError, msg: + print >> sys.stderr, msg + sys.exit(1) + + section = None + fuzzy = 0 + + # Parse the catalog + msgid = msgstr = '' + lno = 0 + for l in lines: + lno += 1 + # If we get a comment line after a msgstr, this is a new entry + if l[0] == '#' and section == STR: + add(msgid, msgstr, fuzzy) + section = None + fuzzy = 0 + # Record a fuzzy mark + if l[:2] == '#,' and (l.find('fuzzy') >= 0): + fuzzy = 1 + # Skip comments + if l[0] == '#': + continue + # Start of msgid_plural section, separate from singular form with \0 + if l.startswith('msgid_plural'): + msgid += '\0' + l = l[12:] + # Now we are in a msgid section, output previous section + elif l.startswith('msgid'): + if section == STR: + add(msgid, msgstr, fuzzy) + section = ID + l = l[5:] + msgid = msgstr = '' + # Now we are in a msgstr section + elif l.startswith('msgstr'): + section = STR + l = l[6:] + # Check for plural forms + if l.startswith('['): + # Separate plural forms with \0 + if not l.startswith('[0]'): + msgstr += '\0' + # Ignore the index - must come in sequence + l = l[l.index(']') + 1:] + # Skip empty lines + l = l.strip() + if not l: + continue + # XXX: Does this always follow Python escape semantics? + l = eval(l) + if section == ID: + msgid += l + elif section == STR: + msgstr += l + else: + print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \ + 'before:' + print >> sys.stderr, l + sys.exit(1) + # Add last entry + if section == STR: + add(msgid, msgstr, fuzzy) + + # Compute output + output = generate() + + try: + open(outfile,"wb").write(output) + except IOError,msg: + print >> sys.stderr, msg + + +def main (): + try: + opts, args = getopt.getopt(sys.argv[1:], 'hVo:', + ['help', 'version', 'output-file=']) + except getopt.error, msg: + usage(1, msg) + + outfile = None + # parse options + for opt, arg in opts: + if opt in ('-h', '--help'): + usage(0) + elif opt in ('-V', '--version'): + print >> sys.stderr, "msgfmt.py", __version__ + sys.exit(0) + elif opt in ('-o', '--output-file'): + outfile = arg + # do it + if not args: + print >> sys.stderr, 'No input file given' + print >> sys.stderr, "Try `msgfmt --help' for more information." + return + + for filename in args: + make(filename, outfile) + + +if __name__ == '__main__': main() +# -*- coding: iso-8859-1 -*- +# Written by Martin v. Lwis +# Plural forms support added by alexander smishlajev +""" +Generate binary message catalog from textual translation description. + +This program converts a textual Uniforum-style message catalog (.po file) into +a binary GNU catalog (.mo file). This is essentially the same function as the +GNU msgfmt program, however, it is a simpler implementation. + +Usage: msgfmt.py [OPTIONS] filename.po + +Options: + -o file + --output-file=file + Specify the output file to write to. If omitted, output will go to a + file named filename.mo (based off the input file name). + + -h + --help + Print this message and exit. + + -V + --version + Display version information and exit. +""" + +import sys +import os +import getopt +import struct +import array + +__version__ = "1.1" + +MESSAGES = {} + + +def usage (ecode, msg=''): + """ + Print usage and msg and exit with given code. + """ + print >> sys.stderr, __doc__ + if msg: + print >> sys.stderr, msg + sys.exit(ecode) + + +def add (msgid, transtr, fuzzy): + """ + Add a non-fuzzy translation to the dictionary. + """ + global MESSAGES + if not fuzzy and transtr and not transtr.startswith('\0'): + MESSAGES[msgid] = transtr + + +def generate (): + """ + Return the generated output. + """ + global MESSAGES + keys = MESSAGES.keys() + # the keys are sorted in the .mo file + keys.sort() + offsets = [] + ids = strs = '' + for _id in keys: + # For each string, we need size and file offset. Each string is NUL + # terminated; the NUL does not count into the size. + offsets.append((len(ids), len(_id), len(strs), len(MESSAGES[_id]))) + ids += _id + '\0' + strs += MESSAGES[_id] + '\0' + output = '' + # The header is 7 32-bit unsigned integers. We don't use hash tables, so + # the keys start right after the index tables. + # translated string. + keystart = 7*4+16*len(keys) + # and the values start after the keys + valuestart = keystart + len(ids) + koffsets = [] + voffsets = [] + # The string table first has the list of keys, then the list of values. + # Each entry has first the size of the string, then the file offset. + for o1, l1, o2, l2 in offsets: + koffsets += [l1, o1+keystart] + voffsets += [l2, o2+valuestart] + offsets = koffsets + voffsets + output = struct.pack("Iiiiiii", + 0x950412deL, # Magic + 0, # Version + len(keys), # # of entries + 7*4, # start of key index + 7*4+len(keys)*8, # start of value index + 0, 0) # size and offset of hash table + output += array.array("i", offsets).tostring() + output += ids + output += strs + return output + + +def make (filename, outfile): + ID = 1 + STR = 2 + global MESSAGES + MESSAGES = {} + + # Compute .mo name from .po name and arguments + if filename.endswith('.po'): + infile = filename + else: + infile = filename + '.po' + if outfile is None: + outfile = os.path.splitext(infile)[0] + '.mo' + + try: + lines = open(infile).readlines() + except IOError, msg: + print >> sys.stderr, msg + sys.exit(1) + + section = None + fuzzy = 0 + + # Parse the catalog + msgid = msgstr = '' + lno = 0 + for l in lines: + lno += 1 + # If we get a comment line after a msgstr, this is a new entry + if l[0] == '#' and section == STR: + add(msgid, msgstr, fuzzy) + section = None + fuzzy = 0 + # Record a fuzzy mark + if l[:2] == '#,' and (l.find('fuzzy') >= 0): + fuzzy = 1 + # Skip comments + if l[0] == '#': + continue + # Start of msgid_plural section, separate from singular form with \0 + if l.startswith('msgid_plural'): + msgid += '\0' + l = l[12:] + # Now we are in a msgid section, output previous section + elif l.startswith('msgid'): + if section == STR: + add(msgid, msgstr, fuzzy) + section = ID + l = l[5:] + msgid = msgstr = '' + # Now we are in a msgstr section + elif l.startswith('msgstr'): + section = STR + l = l[6:] + # Check for plural forms + if l.startswith('['): + # Separate plural forms with \0 + if not l.startswith('[0]'): + msgstr += '\0' + # Ignore the index - must come in sequence + l = l[l.index(']') + 1:] + # Skip empty lines + l = l.strip() + if not l: + continue + # XXX: Does this always follow Python escape semantics? + l = eval(l) + if section == ID: + msgid += l + elif section == STR: + msgstr += l + else: + print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \ + 'before:' + print >> sys.stderr, l + sys.exit(1) + # Add last entry + if section == STR: + add(msgid, msgstr, fuzzy) + + # Compute output + output = generate() + + try: + open(outfile,"wb").write(output) + except IOError,msg: + print >> sys.stderr, msg + + +def main (): + try: + opts, args = getopt.getopt(sys.argv[1:], 'hVo:', + ['help', 'version', 'output-file=']) + except getopt.error, msg: + usage(1, msg) + + outfile = None + # parse options + for opt, arg in opts: + if opt in ('-h', '--help'): + usage(0) + elif opt in ('-V', '--version'): + print >> sys.stderr, "msgfmt.py", __version__ + sys.exit(0) + elif opt in ('-o', '--output-file'): + outfile = arg + # do it + if not args: + print >> sys.stderr, 'No input file given' + print >> sys.stderr, "Try `msgfmt --help' for more information." + return + + for filename in args: + make(filename, outfile) + + +if __name__ == '__main__': + main() diff --git a/pixmaps/flags18x12/ad.png b/pixmaps/flags18x12/ad.png deleted file mode 100644 index 0d2b04c25..000000000 Binary files a/pixmaps/flags18x12/ad.png and /dev/null differ diff --git a/pixmaps/flags18x12/ae.png b/pixmaps/flags18x12/ae.png deleted file mode 100644 index 885be201e..000000000 Binary files a/pixmaps/flags18x12/ae.png and /dev/null differ diff --git a/pixmaps/flags18x12/af.png b/pixmaps/flags18x12/af.png deleted file mode 100644 index d59b3a6dd..000000000 Binary files a/pixmaps/flags18x12/af.png and /dev/null differ diff --git a/pixmaps/flags18x12/ag.png b/pixmaps/flags18x12/ag.png deleted file mode 100644 index 20440ba20..000000000 Binary files a/pixmaps/flags18x12/ag.png and /dev/null differ diff --git a/pixmaps/flags18x12/ai.png b/pixmaps/flags18x12/ai.png deleted file mode 100644 index c71ec8310..000000000 Binary files a/pixmaps/flags18x12/ai.png and /dev/null differ diff --git a/pixmaps/flags18x12/al.png b/pixmaps/flags18x12/al.png deleted file mode 100644 index d37e44ed0..000000000 Binary files a/pixmaps/flags18x12/al.png and /dev/null differ diff --git a/pixmaps/flags18x12/am.png b/pixmaps/flags18x12/am.png deleted file mode 100644 index 043ec6728..000000000 Binary files a/pixmaps/flags18x12/am.png and /dev/null differ diff --git a/pixmaps/flags18x12/an.png b/pixmaps/flags18x12/an.png deleted file mode 100644 index 9ede9b732..000000000 Binary files a/pixmaps/flags18x12/an.png and /dev/null differ diff --git a/pixmaps/flags18x12/ao.png b/pixmaps/flags18x12/ao.png deleted file mode 100644 index 6b5e475c4..000000000 Binary files a/pixmaps/flags18x12/ao.png and /dev/null differ diff --git a/pixmaps/flags18x12/ar.png b/pixmaps/flags18x12/ar.png deleted file mode 100644 index 913bdb9fa..000000000 Binary files a/pixmaps/flags18x12/ar.png and /dev/null differ diff --git a/pixmaps/flags18x12/as.png b/pixmaps/flags18x12/as.png deleted file mode 100644 index 5e6b4cdca..000000000 Binary files a/pixmaps/flags18x12/as.png and /dev/null differ diff --git a/pixmaps/flags18x12/at.png b/pixmaps/flags18x12/at.png deleted file mode 100644 index ee928f171..000000000 Binary files a/pixmaps/flags18x12/at.png and /dev/null differ diff --git a/pixmaps/flags18x12/au.png b/pixmaps/flags18x12/au.png deleted file mode 100644 index 422598a68..000000000 Binary files a/pixmaps/flags18x12/au.png and /dev/null differ diff --git a/pixmaps/flags18x12/aw.png b/pixmaps/flags18x12/aw.png deleted file mode 100644 index 68c9c9864..000000000 Binary files a/pixmaps/flags18x12/aw.png and /dev/null differ diff --git a/pixmaps/flags18x12/ax.png b/pixmaps/flags18x12/ax.png deleted file mode 100644 index 6b834b442..000000000 Binary files a/pixmaps/flags18x12/ax.png and /dev/null differ diff --git a/pixmaps/flags18x12/az.png b/pixmaps/flags18x12/az.png deleted file mode 100644 index c1271f2ed..000000000 Binary files a/pixmaps/flags18x12/az.png and /dev/null differ diff --git a/pixmaps/flags18x12/ba.png b/pixmaps/flags18x12/ba.png deleted file mode 100644 index f4daa7b52..000000000 Binary files a/pixmaps/flags18x12/ba.png and /dev/null differ diff --git a/pixmaps/flags18x12/bb.png b/pixmaps/flags18x12/bb.png deleted file mode 100644 index bebfc7a66..000000000 Binary files a/pixmaps/flags18x12/bb.png and /dev/null differ diff --git a/pixmaps/flags18x12/bd.png b/pixmaps/flags18x12/bd.png deleted file mode 100644 index a72670a08..000000000 Binary files a/pixmaps/flags18x12/bd.png and /dev/null differ diff --git a/pixmaps/flags18x12/be.png b/pixmaps/flags18x12/be.png deleted file mode 100644 index e94e32cce..000000000 Binary files a/pixmaps/flags18x12/be.png and /dev/null differ diff --git a/pixmaps/flags18x12/bf.png b/pixmaps/flags18x12/bf.png deleted file mode 100644 index cd51c286f..000000000 Binary files a/pixmaps/flags18x12/bf.png and /dev/null differ diff --git a/pixmaps/flags18x12/bg.png b/pixmaps/flags18x12/bg.png deleted file mode 100644 index 28544ef15..000000000 Binary files a/pixmaps/flags18x12/bg.png and /dev/null differ diff --git a/pixmaps/flags18x12/bh.png b/pixmaps/flags18x12/bh.png deleted file mode 100644 index 5cee8eec3..000000000 Binary files a/pixmaps/flags18x12/bh.png and /dev/null differ diff --git a/pixmaps/flags18x12/bi.png b/pixmaps/flags18x12/bi.png deleted file mode 100644 index d3ff9476f..000000000 Binary files a/pixmaps/flags18x12/bi.png and /dev/null differ diff --git a/pixmaps/flags18x12/bj.png b/pixmaps/flags18x12/bj.png deleted file mode 100644 index 010bc3579..000000000 Binary files a/pixmaps/flags18x12/bj.png and /dev/null differ diff --git a/pixmaps/flags18x12/bm.png b/pixmaps/flags18x12/bm.png deleted file mode 100644 index 8f282aa27..000000000 Binary files a/pixmaps/flags18x12/bm.png and /dev/null differ diff --git a/pixmaps/flags18x12/bn.png b/pixmaps/flags18x12/bn.png deleted file mode 100644 index f1272b99d..000000000 Binary files a/pixmaps/flags18x12/bn.png and /dev/null differ diff --git a/pixmaps/flags18x12/bo.png b/pixmaps/flags18x12/bo.png deleted file mode 100644 index dcb2303aa..000000000 Binary files a/pixmaps/flags18x12/bo.png and /dev/null differ diff --git a/pixmaps/flags18x12/br.png b/pixmaps/flags18x12/br.png deleted file mode 100644 index 38f81c4aa..000000000 Binary files a/pixmaps/flags18x12/br.png and /dev/null differ diff --git a/pixmaps/flags18x12/bs.png b/pixmaps/flags18x12/bs.png deleted file mode 100644 index d1708dda7..000000000 Binary files a/pixmaps/flags18x12/bs.png and /dev/null differ diff --git a/pixmaps/flags18x12/bt.png b/pixmaps/flags18x12/bt.png deleted file mode 100644 index d39c1fc06..000000000 Binary files a/pixmaps/flags18x12/bt.png and /dev/null differ diff --git a/pixmaps/flags18x12/bv.png b/pixmaps/flags18x12/bv.png deleted file mode 100644 index bac14bc40..000000000 Binary files a/pixmaps/flags18x12/bv.png and /dev/null differ diff --git a/pixmaps/flags18x12/bw.png b/pixmaps/flags18x12/bw.png deleted file mode 100644 index b372b23f8..000000000 Binary files a/pixmaps/flags18x12/bw.png and /dev/null differ diff --git a/pixmaps/flags18x12/by.png b/pixmaps/flags18x12/by.png deleted file mode 100644 index e217a8295..000000000 Binary files a/pixmaps/flags18x12/by.png and /dev/null differ diff --git a/pixmaps/flags18x12/bz.png b/pixmaps/flags18x12/bz.png deleted file mode 100644 index 87e7e76f9..000000000 Binary files a/pixmaps/flags18x12/bz.png and /dev/null differ diff --git a/pixmaps/flags18x12/ca.png b/pixmaps/flags18x12/ca.png deleted file mode 100644 index 182b51e3a..000000000 Binary files a/pixmaps/flags18x12/ca.png and /dev/null differ diff --git a/pixmaps/flags18x12/cc.png b/pixmaps/flags18x12/cc.png deleted file mode 100644 index 82310fa87..000000000 Binary files a/pixmaps/flags18x12/cc.png and /dev/null differ diff --git a/pixmaps/flags18x12/cd.png b/pixmaps/flags18x12/cd.png deleted file mode 100644 index e555370eb..000000000 Binary files a/pixmaps/flags18x12/cd.png and /dev/null differ diff --git a/pixmaps/flags18x12/cf.png b/pixmaps/flags18x12/cf.png deleted file mode 100644 index 0e797cc5c..000000000 Binary files a/pixmaps/flags18x12/cf.png and /dev/null differ diff --git a/pixmaps/flags18x12/cg.png b/pixmaps/flags18x12/cg.png deleted file mode 100644 index 83ecf4aa0..000000000 Binary files a/pixmaps/flags18x12/cg.png and /dev/null differ diff --git a/pixmaps/flags18x12/ch.png b/pixmaps/flags18x12/ch.png deleted file mode 100644 index 47af5323c..000000000 Binary files a/pixmaps/flags18x12/ch.png and /dev/null differ diff --git a/pixmaps/flags18x12/ci.png b/pixmaps/flags18x12/ci.png deleted file mode 100644 index c15d564bb..000000000 Binary files a/pixmaps/flags18x12/ci.png and /dev/null differ diff --git a/pixmaps/flags18x12/ck.png b/pixmaps/flags18x12/ck.png deleted file mode 100644 index 9eaf66ceb..000000000 Binary files a/pixmaps/flags18x12/ck.png and /dev/null differ diff --git a/pixmaps/flags18x12/cl.png b/pixmaps/flags18x12/cl.png deleted file mode 100644 index a15e5a910..000000000 Binary files a/pixmaps/flags18x12/cl.png and /dev/null differ diff --git a/pixmaps/flags18x12/cm.png b/pixmaps/flags18x12/cm.png deleted file mode 100644 index 633480892..000000000 Binary files a/pixmaps/flags18x12/cm.png and /dev/null differ diff --git a/pixmaps/flags18x12/cn.png b/pixmaps/flags18x12/cn.png deleted file mode 100644 index cfb61ee32..000000000 Binary files a/pixmaps/flags18x12/cn.png and /dev/null differ diff --git a/pixmaps/flags18x12/co.png b/pixmaps/flags18x12/co.png deleted file mode 100644 index c68ade012..000000000 Binary files a/pixmaps/flags18x12/co.png and /dev/null differ diff --git a/pixmaps/flags18x12/cr.png b/pixmaps/flags18x12/cr.png deleted file mode 100644 index b9c89a01c..000000000 Binary files a/pixmaps/flags18x12/cr.png and /dev/null differ diff --git a/pixmaps/flags18x12/cs.png b/pixmaps/flags18x12/cs.png deleted file mode 100644 index 9355b9329..000000000 Binary files a/pixmaps/flags18x12/cs.png and /dev/null differ diff --git a/pixmaps/flags18x12/cu.png b/pixmaps/flags18x12/cu.png deleted file mode 100644 index f9abb7102..000000000 Binary files a/pixmaps/flags18x12/cu.png and /dev/null differ diff --git a/pixmaps/flags18x12/cv.png b/pixmaps/flags18x12/cv.png deleted file mode 100644 index df1d52588..000000000 Binary files a/pixmaps/flags18x12/cv.png and /dev/null differ diff --git a/pixmaps/flags18x12/cx.png b/pixmaps/flags18x12/cx.png deleted file mode 100644 index e1978521c..000000000 Binary files a/pixmaps/flags18x12/cx.png and /dev/null differ diff --git a/pixmaps/flags18x12/cy.png b/pixmaps/flags18x12/cy.png deleted file mode 100644 index 564232b35..000000000 Binary files a/pixmaps/flags18x12/cy.png and /dev/null differ diff --git a/pixmaps/flags18x12/cz.png b/pixmaps/flags18x12/cz.png deleted file mode 100644 index dcc14c6c8..000000000 Binary files a/pixmaps/flags18x12/cz.png and /dev/null differ diff --git a/pixmaps/flags18x12/de.png b/pixmaps/flags18x12/de.png deleted file mode 100644 index 8c688c9c2..000000000 Binary files a/pixmaps/flags18x12/de.png and /dev/null differ diff --git a/pixmaps/flags18x12/dj.png b/pixmaps/flags18x12/dj.png deleted file mode 100644 index a9b2adf70..000000000 Binary files a/pixmaps/flags18x12/dj.png and /dev/null differ diff --git a/pixmaps/flags18x12/dk.png b/pixmaps/flags18x12/dk.png deleted file mode 100644 index e73bcee24..000000000 Binary files a/pixmaps/flags18x12/dk.png and /dev/null differ diff --git a/pixmaps/flags18x12/dm.png b/pixmaps/flags18x12/dm.png deleted file mode 100644 index 31fa4cd1d..000000000 Binary files a/pixmaps/flags18x12/dm.png and /dev/null differ diff --git a/pixmaps/flags18x12/do.png b/pixmaps/flags18x12/do.png deleted file mode 100644 index 818b2ce30..000000000 Binary files a/pixmaps/flags18x12/do.png and /dev/null differ diff --git a/pixmaps/flags18x12/dz.png b/pixmaps/flags18x12/dz.png deleted file mode 100644 index 246c73c3e..000000000 Binary files a/pixmaps/flags18x12/dz.png and /dev/null differ diff --git a/pixmaps/flags18x12/ec.png b/pixmaps/flags18x12/ec.png deleted file mode 100644 index febddf840..000000000 Binary files a/pixmaps/flags18x12/ec.png and /dev/null differ diff --git a/pixmaps/flags18x12/ee.png b/pixmaps/flags18x12/ee.png deleted file mode 100644 index f6e109f51..000000000 Binary files a/pixmaps/flags18x12/ee.png and /dev/null differ diff --git a/pixmaps/flags18x12/eg.png b/pixmaps/flags18x12/eg.png deleted file mode 100644 index 6c32efbc6..000000000 Binary files a/pixmaps/flags18x12/eg.png and /dev/null differ diff --git a/pixmaps/flags18x12/eh.png b/pixmaps/flags18x12/eh.png deleted file mode 100644 index fe0918685..000000000 Binary files a/pixmaps/flags18x12/eh.png and /dev/null differ diff --git a/pixmaps/flags18x12/er.png b/pixmaps/flags18x12/er.png deleted file mode 100644 index a91ef3f8b..000000000 Binary files a/pixmaps/flags18x12/er.png and /dev/null differ diff --git a/pixmaps/flags18x12/es.png b/pixmaps/flags18x12/es.png deleted file mode 100644 index bfe7b69c4..000000000 Binary files a/pixmaps/flags18x12/es.png and /dev/null differ diff --git a/pixmaps/flags18x12/et.png b/pixmaps/flags18x12/et.png deleted file mode 100644 index 0b642741d..000000000 Binary files a/pixmaps/flags18x12/et.png and /dev/null differ diff --git a/pixmaps/flags18x12/fi.png b/pixmaps/flags18x12/fi.png deleted file mode 100644 index 8637023f8..000000000 Binary files a/pixmaps/flags18x12/fi.png and /dev/null differ diff --git a/pixmaps/flags18x12/fj.png b/pixmaps/flags18x12/fj.png deleted file mode 100644 index 0aab514ab..000000000 Binary files a/pixmaps/flags18x12/fj.png and /dev/null differ diff --git a/pixmaps/flags18x12/fk.png b/pixmaps/flags18x12/fk.png deleted file mode 100644 index 2b721f96d..000000000 Binary files a/pixmaps/flags18x12/fk.png and /dev/null differ diff --git a/pixmaps/flags18x12/fm.png b/pixmaps/flags18x12/fm.png deleted file mode 100644 index 1a910645a..000000000 Binary files a/pixmaps/flags18x12/fm.png and /dev/null differ diff --git a/pixmaps/flags18x12/fo.png b/pixmaps/flags18x12/fo.png deleted file mode 100644 index 4bf6eddfb..000000000 Binary files a/pixmaps/flags18x12/fo.png and /dev/null differ diff --git a/pixmaps/flags18x12/fr.png b/pixmaps/flags18x12/fr.png deleted file mode 100644 index d4616ed1f..000000000 Binary files a/pixmaps/flags18x12/fr.png and /dev/null differ diff --git a/pixmaps/flags18x12/ga.png b/pixmaps/flags18x12/ga.png deleted file mode 100644 index 1f1788cd3..000000000 Binary files a/pixmaps/flags18x12/ga.png and /dev/null differ diff --git a/pixmaps/flags18x12/gb.png b/pixmaps/flags18x12/gb.png deleted file mode 100644 index e0ce9a66a..000000000 Binary files a/pixmaps/flags18x12/gb.png and /dev/null differ diff --git a/pixmaps/flags18x12/gd.png b/pixmaps/flags18x12/gd.png deleted file mode 100644 index 70467ac36..000000000 Binary files a/pixmaps/flags18x12/gd.png and /dev/null differ diff --git a/pixmaps/flags18x12/ge.png b/pixmaps/flags18x12/ge.png deleted file mode 100644 index 11260b6bc..000000000 Binary files a/pixmaps/flags18x12/ge.png and /dev/null differ diff --git a/pixmaps/flags18x12/gf.png b/pixmaps/flags18x12/gf.png deleted file mode 100644 index d4616ed1f..000000000 Binary files a/pixmaps/flags18x12/gf.png and /dev/null differ diff --git a/pixmaps/flags18x12/gh.png b/pixmaps/flags18x12/gh.png deleted file mode 100644 index 3f3b980fb..000000000 Binary files a/pixmaps/flags18x12/gh.png and /dev/null differ diff --git a/pixmaps/flags18x12/gi.png b/pixmaps/flags18x12/gi.png deleted file mode 100644 index 54d6eb103..000000000 Binary files a/pixmaps/flags18x12/gi.png and /dev/null differ diff --git a/pixmaps/flags18x12/gl.png b/pixmaps/flags18x12/gl.png deleted file mode 100644 index ef5ead591..000000000 Binary files a/pixmaps/flags18x12/gl.png and /dev/null differ diff --git a/pixmaps/flags18x12/gm.png b/pixmaps/flags18x12/gm.png deleted file mode 100644 index 95cce12dd..000000000 Binary files a/pixmaps/flags18x12/gm.png and /dev/null differ diff --git a/pixmaps/flags18x12/gn.png b/pixmaps/flags18x12/gn.png deleted file mode 100644 index 5f8bba11b..000000000 Binary files a/pixmaps/flags18x12/gn.png and /dev/null differ diff --git a/pixmaps/flags18x12/gp.png b/pixmaps/flags18x12/gp.png deleted file mode 100644 index d4616ed1f..000000000 Binary files a/pixmaps/flags18x12/gp.png and /dev/null differ diff --git a/pixmaps/flags18x12/gq.png b/pixmaps/flags18x12/gq.png deleted file mode 100644 index 2cbd4a89a..000000000 Binary files a/pixmaps/flags18x12/gq.png and /dev/null differ diff --git a/pixmaps/flags18x12/gr.png b/pixmaps/flags18x12/gr.png deleted file mode 100644 index a5b70ad2d..000000000 Binary files a/pixmaps/flags18x12/gr.png and /dev/null differ diff --git a/pixmaps/flags18x12/gs.png b/pixmaps/flags18x12/gs.png deleted file mode 100644 index 770617135..000000000 Binary files a/pixmaps/flags18x12/gs.png and /dev/null differ diff --git a/pixmaps/flags18x12/gt.png b/pixmaps/flags18x12/gt.png deleted file mode 100644 index ce82c343a..000000000 Binary files a/pixmaps/flags18x12/gt.png and /dev/null differ diff --git a/pixmaps/flags18x12/gu.png b/pixmaps/flags18x12/gu.png deleted file mode 100644 index 1d2dc8731..000000000 Binary files a/pixmaps/flags18x12/gu.png and /dev/null differ diff --git a/pixmaps/flags18x12/gw.png b/pixmaps/flags18x12/gw.png deleted file mode 100644 index 5e70972a4..000000000 Binary files a/pixmaps/flags18x12/gw.png and /dev/null differ diff --git a/pixmaps/flags18x12/gy.png b/pixmaps/flags18x12/gy.png deleted file mode 100644 index ae7c645dd..000000000 Binary files a/pixmaps/flags18x12/gy.png and /dev/null differ diff --git a/pixmaps/flags18x12/hk.png b/pixmaps/flags18x12/hk.png deleted file mode 100644 index 0bc072052..000000000 Binary files a/pixmaps/flags18x12/hk.png and /dev/null differ diff --git a/pixmaps/flags18x12/hm.png b/pixmaps/flags18x12/hm.png deleted file mode 100644 index 214924d27..000000000 Binary files a/pixmaps/flags18x12/hm.png and /dev/null differ diff --git a/pixmaps/flags18x12/hn.png b/pixmaps/flags18x12/hn.png deleted file mode 100644 index de08a367b..000000000 Binary files a/pixmaps/flags18x12/hn.png and /dev/null differ diff --git a/pixmaps/flags18x12/hr.png b/pixmaps/flags18x12/hr.png deleted file mode 100644 index 69eeed334..000000000 Binary files a/pixmaps/flags18x12/hr.png and /dev/null differ diff --git a/pixmaps/flags18x12/ht.png b/pixmaps/flags18x12/ht.png deleted file mode 100644 index 8369277b7..000000000 Binary files a/pixmaps/flags18x12/ht.png and /dev/null differ diff --git a/pixmaps/flags18x12/hu.png b/pixmaps/flags18x12/hu.png deleted file mode 100644 index 0d492a04d..000000000 Binary files a/pixmaps/flags18x12/hu.png and /dev/null differ diff --git a/pixmaps/flags18x12/id.png b/pixmaps/flags18x12/id.png deleted file mode 100644 index 14e91f92a..000000000 Binary files a/pixmaps/flags18x12/id.png and /dev/null differ diff --git a/pixmaps/flags18x12/ie.png b/pixmaps/flags18x12/ie.png deleted file mode 100644 index 839c3106f..000000000 Binary files a/pixmaps/flags18x12/ie.png and /dev/null differ diff --git a/pixmaps/flags18x12/il.png b/pixmaps/flags18x12/il.png deleted file mode 100644 index 31cf02dec..000000000 Binary files a/pixmaps/flags18x12/il.png and /dev/null differ diff --git a/pixmaps/flags18x12/in.png b/pixmaps/flags18x12/in.png deleted file mode 100644 index 92737dbda..000000000 Binary files a/pixmaps/flags18x12/in.png and /dev/null differ diff --git a/pixmaps/flags18x12/io.png b/pixmaps/flags18x12/io.png deleted file mode 100644 index 9ece8abe7..000000000 Binary files a/pixmaps/flags18x12/io.png and /dev/null differ diff --git a/pixmaps/flags18x12/iq.png b/pixmaps/flags18x12/iq.png deleted file mode 100644 index f73741913..000000000 Binary files a/pixmaps/flags18x12/iq.png and /dev/null differ diff --git a/pixmaps/flags18x12/ir.png b/pixmaps/flags18x12/ir.png deleted file mode 100644 index e81a0f677..000000000 Binary files a/pixmaps/flags18x12/ir.png and /dev/null differ diff --git a/pixmaps/flags18x12/is.png b/pixmaps/flags18x12/is.png deleted file mode 100644 index 8bf828728..000000000 Binary files a/pixmaps/flags18x12/is.png and /dev/null differ diff --git a/pixmaps/flags18x12/it.png b/pixmaps/flags18x12/it.png deleted file mode 100644 index e0cab7297..000000000 Binary files a/pixmaps/flags18x12/it.png and /dev/null differ diff --git a/pixmaps/flags18x12/jm.png b/pixmaps/flags18x12/jm.png deleted file mode 100644 index f3021b5f7..000000000 Binary files a/pixmaps/flags18x12/jm.png and /dev/null differ diff --git a/pixmaps/flags18x12/jo.png b/pixmaps/flags18x12/jo.png deleted file mode 100644 index e39b14e05..000000000 Binary files a/pixmaps/flags18x12/jo.png and /dev/null differ diff --git a/pixmaps/flags18x12/jp.png b/pixmaps/flags18x12/jp.png deleted file mode 100644 index 506a5356e..000000000 Binary files a/pixmaps/flags18x12/jp.png and /dev/null differ diff --git a/pixmaps/flags18x12/ke.png b/pixmaps/flags18x12/ke.png deleted file mode 100644 index ffb150afd..000000000 Binary files a/pixmaps/flags18x12/ke.png and /dev/null differ diff --git a/pixmaps/flags18x12/kg.png b/pixmaps/flags18x12/kg.png deleted file mode 100644 index aceeb6c61..000000000 Binary files a/pixmaps/flags18x12/kg.png and /dev/null differ diff --git a/pixmaps/flags18x12/kh.png b/pixmaps/flags18x12/kh.png deleted file mode 100644 index c64d08aa9..000000000 Binary files a/pixmaps/flags18x12/kh.png and /dev/null differ diff --git a/pixmaps/flags18x12/ki.png b/pixmaps/flags18x12/ki.png deleted file mode 100644 index 510e344bb..000000000 Binary files a/pixmaps/flags18x12/ki.png and /dev/null differ diff --git a/pixmaps/flags18x12/km.png b/pixmaps/flags18x12/km.png deleted file mode 100644 index f0aab2ea7..000000000 Binary files a/pixmaps/flags18x12/km.png and /dev/null differ diff --git a/pixmaps/flags18x12/kn.png b/pixmaps/flags18x12/kn.png deleted file mode 100644 index 887c87cfd..000000000 Binary files a/pixmaps/flags18x12/kn.png and /dev/null differ diff --git a/pixmaps/flags18x12/kp.png b/pixmaps/flags18x12/kp.png deleted file mode 100644 index 653e82f63..000000000 Binary files a/pixmaps/flags18x12/kp.png and /dev/null differ diff --git a/pixmaps/flags18x12/kr.png b/pixmaps/flags18x12/kr.png deleted file mode 100644 index ac8276643..000000000 Binary files a/pixmaps/flags18x12/kr.png and /dev/null differ diff --git a/pixmaps/flags18x12/kw.png b/pixmaps/flags18x12/kw.png deleted file mode 100644 index a4c27ffd5..000000000 Binary files a/pixmaps/flags18x12/kw.png and /dev/null differ diff --git a/pixmaps/flags18x12/ky.png b/pixmaps/flags18x12/ky.png deleted file mode 100644 index c7f14c4dd..000000000 Binary files a/pixmaps/flags18x12/ky.png and /dev/null differ diff --git a/pixmaps/flags18x12/kz.png b/pixmaps/flags18x12/kz.png deleted file mode 100644 index 38f75b20a..000000000 Binary files a/pixmaps/flags18x12/kz.png and /dev/null differ diff --git a/pixmaps/flags18x12/la.png b/pixmaps/flags18x12/la.png deleted file mode 100644 index fd70e0475..000000000 Binary files a/pixmaps/flags18x12/la.png and /dev/null differ diff --git a/pixmaps/flags18x12/lb.png b/pixmaps/flags18x12/lb.png deleted file mode 100644 index 48043644c..000000000 Binary files a/pixmaps/flags18x12/lb.png and /dev/null differ diff --git a/pixmaps/flags18x12/lc.png b/pixmaps/flags18x12/lc.png deleted file mode 100644 index 971b03a70..000000000 Binary files a/pixmaps/flags18x12/lc.png and /dev/null differ diff --git a/pixmaps/flags18x12/li.png b/pixmaps/flags18x12/li.png deleted file mode 100644 index cd6eb0893..000000000 Binary files a/pixmaps/flags18x12/li.png and /dev/null differ diff --git a/pixmaps/flags18x12/lk.png b/pixmaps/flags18x12/lk.png deleted file mode 100644 index 500c9355f..000000000 Binary files a/pixmaps/flags18x12/lk.png and /dev/null differ diff --git a/pixmaps/flags18x12/lr.png b/pixmaps/flags18x12/lr.png deleted file mode 100644 index a77998406..000000000 Binary files a/pixmaps/flags18x12/lr.png and /dev/null differ diff --git a/pixmaps/flags18x12/ls.png b/pixmaps/flags18x12/ls.png deleted file mode 100644 index 892bc44df..000000000 Binary files a/pixmaps/flags18x12/ls.png and /dev/null differ diff --git a/pixmaps/flags18x12/lt.png b/pixmaps/flags18x12/lt.png deleted file mode 100644 index 2bd0203a5..000000000 Binary files a/pixmaps/flags18x12/lt.png and /dev/null differ diff --git a/pixmaps/flags18x12/lu.png b/pixmaps/flags18x12/lu.png deleted file mode 100644 index dab8533cb..000000000 Binary files a/pixmaps/flags18x12/lu.png and /dev/null differ diff --git a/pixmaps/flags18x12/lv.png b/pixmaps/flags18x12/lv.png deleted file mode 100644 index abba0cd5c..000000000 Binary files a/pixmaps/flags18x12/lv.png and /dev/null differ diff --git a/pixmaps/flags18x12/ly.png b/pixmaps/flags18x12/ly.png deleted file mode 100644 index 7bce7778a..000000000 Binary files a/pixmaps/flags18x12/ly.png and /dev/null differ diff --git a/pixmaps/flags18x12/ma.png b/pixmaps/flags18x12/ma.png deleted file mode 100644 index c21eef1cc..000000000 Binary files a/pixmaps/flags18x12/ma.png and /dev/null differ diff --git a/pixmaps/flags18x12/mc.png b/pixmaps/flags18x12/mc.png deleted file mode 100644 index b33762c50..000000000 Binary files a/pixmaps/flags18x12/mc.png and /dev/null differ diff --git a/pixmaps/flags18x12/md.png b/pixmaps/flags18x12/md.png deleted file mode 100644 index 5441949d8..000000000 Binary files a/pixmaps/flags18x12/md.png and /dev/null differ diff --git a/pixmaps/flags18x12/me.png b/pixmaps/flags18x12/me.png deleted file mode 100644 index 7f9ed152a..000000000 Binary files a/pixmaps/flags18x12/me.png and /dev/null differ diff --git a/pixmaps/flags18x12/mg.png b/pixmaps/flags18x12/mg.png deleted file mode 100644 index 5a86b6107..000000000 Binary files a/pixmaps/flags18x12/mg.png and /dev/null differ diff --git a/pixmaps/flags18x12/mh.png b/pixmaps/flags18x12/mh.png deleted file mode 100644 index 7463976dc..000000000 Binary files a/pixmaps/flags18x12/mh.png and /dev/null differ diff --git a/pixmaps/flags18x12/mk.png b/pixmaps/flags18x12/mk.png deleted file mode 100644 index a981b835a..000000000 Binary files a/pixmaps/flags18x12/mk.png and /dev/null differ diff --git a/pixmaps/flags18x12/ml.png b/pixmaps/flags18x12/ml.png deleted file mode 100644 index 36a632ee0..000000000 Binary files a/pixmaps/flags18x12/ml.png and /dev/null differ diff --git a/pixmaps/flags18x12/mm.png b/pixmaps/flags18x12/mm.png deleted file mode 100644 index 86ecd2c80..000000000 Binary files a/pixmaps/flags18x12/mm.png and /dev/null differ diff --git a/pixmaps/flags18x12/mn.png b/pixmaps/flags18x12/mn.png deleted file mode 100644 index 4f7adc7c8..000000000 Binary files a/pixmaps/flags18x12/mn.png and /dev/null differ diff --git a/pixmaps/flags18x12/mo.png b/pixmaps/flags18x12/mo.png deleted file mode 100644 index 4cba9b407..000000000 Binary files a/pixmaps/flags18x12/mo.png and /dev/null differ diff --git a/pixmaps/flags18x12/mp.png b/pixmaps/flags18x12/mp.png deleted file mode 100644 index 6c782fcb1..000000000 Binary files a/pixmaps/flags18x12/mp.png and /dev/null differ diff --git a/pixmaps/flags18x12/mq.png b/pixmaps/flags18x12/mq.png deleted file mode 100644 index d4616ed1f..000000000 Binary files a/pixmaps/flags18x12/mq.png and /dev/null differ diff --git a/pixmaps/flags18x12/mr.png b/pixmaps/flags18x12/mr.png deleted file mode 100644 index 1460ab7c4..000000000 Binary files a/pixmaps/flags18x12/mr.png and /dev/null differ diff --git a/pixmaps/flags18x12/ms.png b/pixmaps/flags18x12/ms.png deleted file mode 100644 index 526f512e3..000000000 Binary files a/pixmaps/flags18x12/ms.png and /dev/null differ diff --git a/pixmaps/flags18x12/mt.png b/pixmaps/flags18x12/mt.png deleted file mode 100644 index 611a45933..000000000 Binary files a/pixmaps/flags18x12/mt.png and /dev/null differ diff --git a/pixmaps/flags18x12/mu.png b/pixmaps/flags18x12/mu.png deleted file mode 100644 index d8b22ccf0..000000000 Binary files a/pixmaps/flags18x12/mu.png and /dev/null differ diff --git a/pixmaps/flags18x12/mv.png b/pixmaps/flags18x12/mv.png deleted file mode 100644 index 0024b864a..000000000 Binary files a/pixmaps/flags18x12/mv.png and /dev/null differ diff --git a/pixmaps/flags18x12/mw.png b/pixmaps/flags18x12/mw.png deleted file mode 100644 index 975fb0a50..000000000 Binary files a/pixmaps/flags18x12/mw.png and /dev/null differ diff --git a/pixmaps/flags18x12/mx.png b/pixmaps/flags18x12/mx.png deleted file mode 100644 index 8b705e4b3..000000000 Binary files a/pixmaps/flags18x12/mx.png and /dev/null differ diff --git a/pixmaps/flags18x12/my.png b/pixmaps/flags18x12/my.png deleted file mode 100644 index 45a827783..000000000 Binary files a/pixmaps/flags18x12/my.png and /dev/null differ diff --git a/pixmaps/flags18x12/mz.png b/pixmaps/flags18x12/mz.png deleted file mode 100644 index 14c7e9c45..000000000 Binary files a/pixmaps/flags18x12/mz.png and /dev/null differ diff --git a/pixmaps/flags18x12/na.png b/pixmaps/flags18x12/na.png deleted file mode 100644 index 64df913b8..000000000 Binary files a/pixmaps/flags18x12/na.png and /dev/null differ diff --git a/pixmaps/flags18x12/nc.png b/pixmaps/flags18x12/nc.png deleted file mode 100644 index d4616ed1f..000000000 Binary files a/pixmaps/flags18x12/nc.png and /dev/null differ diff --git a/pixmaps/flags18x12/ne.png b/pixmaps/flags18x12/ne.png deleted file mode 100644 index 8e6eb323a..000000000 Binary files a/pixmaps/flags18x12/ne.png and /dev/null differ diff --git a/pixmaps/flags18x12/nf.png b/pixmaps/flags18x12/nf.png deleted file mode 100644 index 1f6e81410..000000000 Binary files a/pixmaps/flags18x12/nf.png and /dev/null differ diff --git a/pixmaps/flags18x12/ng.png b/pixmaps/flags18x12/ng.png deleted file mode 100644 index 46dceb270..000000000 Binary files a/pixmaps/flags18x12/ng.png and /dev/null differ diff --git a/pixmaps/flags18x12/ni.png b/pixmaps/flags18x12/ni.png deleted file mode 100644 index 452706578..000000000 Binary files a/pixmaps/flags18x12/ni.png and /dev/null differ diff --git a/pixmaps/flags18x12/nl.png b/pixmaps/flags18x12/nl.png deleted file mode 100644 index 9f5e06340..000000000 Binary files a/pixmaps/flags18x12/nl.png and /dev/null differ diff --git a/pixmaps/flags18x12/no.png b/pixmaps/flags18x12/no.png deleted file mode 100644 index bac14bc40..000000000 Binary files a/pixmaps/flags18x12/no.png and /dev/null differ diff --git a/pixmaps/flags18x12/np.png b/pixmaps/flags18x12/np.png deleted file mode 100644 index 7d0261652..000000000 Binary files a/pixmaps/flags18x12/np.png and /dev/null differ diff --git a/pixmaps/flags18x12/nr.png b/pixmaps/flags18x12/nr.png deleted file mode 100644 index 599353a79..000000000 Binary files a/pixmaps/flags18x12/nr.png and /dev/null differ diff --git a/pixmaps/flags18x12/nu.png b/pixmaps/flags18x12/nu.png deleted file mode 100644 index eafce7b27..000000000 Binary files a/pixmaps/flags18x12/nu.png and /dev/null differ diff --git a/pixmaps/flags18x12/nz.png b/pixmaps/flags18x12/nz.png deleted file mode 100644 index 36a08b14d..000000000 Binary files a/pixmaps/flags18x12/nz.png and /dev/null differ diff --git a/pixmaps/flags18x12/om.png b/pixmaps/flags18x12/om.png deleted file mode 100644 index 13f67d91e..000000000 Binary files a/pixmaps/flags18x12/om.png and /dev/null differ diff --git a/pixmaps/flags18x12/pa.png b/pixmaps/flags18x12/pa.png deleted file mode 100644 index 5d7356cc7..000000000 Binary files a/pixmaps/flags18x12/pa.png and /dev/null differ diff --git a/pixmaps/flags18x12/pe.png b/pixmaps/flags18x12/pe.png deleted file mode 100644 index 913b23a20..000000000 Binary files a/pixmaps/flags18x12/pe.png and /dev/null differ diff --git a/pixmaps/flags18x12/pf.png b/pixmaps/flags18x12/pf.png deleted file mode 100644 index 049a2df3e..000000000 Binary files a/pixmaps/flags18x12/pf.png and /dev/null differ diff --git a/pixmaps/flags18x12/pg.png b/pixmaps/flags18x12/pg.png deleted file mode 100644 index d70415489..000000000 Binary files a/pixmaps/flags18x12/pg.png and /dev/null differ diff --git a/pixmaps/flags18x12/ph.png b/pixmaps/flags18x12/ph.png deleted file mode 100644 index f5427019b..000000000 Binary files a/pixmaps/flags18x12/ph.png and /dev/null differ diff --git a/pixmaps/flags18x12/pk.png b/pixmaps/flags18x12/pk.png deleted file mode 100644 index f644d24ac..000000000 Binary files a/pixmaps/flags18x12/pk.png and /dev/null differ diff --git a/pixmaps/flags18x12/pl.png b/pixmaps/flags18x12/pl.png deleted file mode 100644 index bacf1fac9..000000000 Binary files a/pixmaps/flags18x12/pl.png and /dev/null differ diff --git a/pixmaps/flags18x12/pm.png b/pixmaps/flags18x12/pm.png deleted file mode 100644 index d4616ed1f..000000000 Binary files a/pixmaps/flags18x12/pm.png and /dev/null differ diff --git a/pixmaps/flags18x12/pn.png b/pixmaps/flags18x12/pn.png deleted file mode 100644 index f5743c590..000000000 Binary files a/pixmaps/flags18x12/pn.png and /dev/null differ diff --git a/pixmaps/flags18x12/pr.png b/pixmaps/flags18x12/pr.png deleted file mode 100644 index 88d368020..000000000 Binary files a/pixmaps/flags18x12/pr.png and /dev/null differ diff --git a/pixmaps/flags18x12/ps.png b/pixmaps/flags18x12/ps.png deleted file mode 100644 index 94c651258..000000000 Binary files a/pixmaps/flags18x12/ps.png and /dev/null differ diff --git a/pixmaps/flags18x12/pt.png b/pixmaps/flags18x12/pt.png deleted file mode 100644 index bc8f3977f..000000000 Binary files a/pixmaps/flags18x12/pt.png and /dev/null differ diff --git a/pixmaps/flags18x12/pw.png b/pixmaps/flags18x12/pw.png deleted file mode 100644 index 6ab9422e2..000000000 Binary files a/pixmaps/flags18x12/pw.png and /dev/null differ diff --git a/pixmaps/flags18x12/py.png b/pixmaps/flags18x12/py.png deleted file mode 100644 index 5ebaaefbc..000000000 Binary files a/pixmaps/flags18x12/py.png and /dev/null differ diff --git a/pixmaps/flags18x12/qa.png b/pixmaps/flags18x12/qa.png deleted file mode 100644 index 71f70e559..000000000 Binary files a/pixmaps/flags18x12/qa.png and /dev/null differ diff --git a/pixmaps/flags18x12/re.png b/pixmaps/flags18x12/re.png deleted file mode 100644 index d4616ed1f..000000000 Binary files a/pixmaps/flags18x12/re.png and /dev/null differ diff --git a/pixmaps/flags18x12/ro.png b/pixmaps/flags18x12/ro.png deleted file mode 100644 index cf8e057dd..000000000 Binary files a/pixmaps/flags18x12/ro.png and /dev/null differ diff --git a/pixmaps/flags18x12/rs.png b/pixmaps/flags18x12/rs.png deleted file mode 100644 index 3da1f485a..000000000 Binary files a/pixmaps/flags18x12/rs.png and /dev/null differ diff --git a/pixmaps/flags18x12/ru.png b/pixmaps/flags18x12/ru.png deleted file mode 100644 index 712abb308..000000000 Binary files a/pixmaps/flags18x12/ru.png and /dev/null differ diff --git a/pixmaps/flags18x12/rw.png b/pixmaps/flags18x12/rw.png deleted file mode 100644 index 774d03594..000000000 Binary files a/pixmaps/flags18x12/rw.png and /dev/null differ diff --git a/pixmaps/flags18x12/sa.png b/pixmaps/flags18x12/sa.png deleted file mode 100644 index 470c3eddc..000000000 Binary files a/pixmaps/flags18x12/sa.png and /dev/null differ diff --git a/pixmaps/flags18x12/sb.png b/pixmaps/flags18x12/sb.png deleted file mode 100644 index fdc0d4bba..000000000 Binary files a/pixmaps/flags18x12/sb.png and /dev/null differ diff --git a/pixmaps/flags18x12/sc.png b/pixmaps/flags18x12/sc.png deleted file mode 100644 index 804ff9840..000000000 Binary files a/pixmaps/flags18x12/sc.png and /dev/null differ diff --git a/pixmaps/flags18x12/sd.png b/pixmaps/flags18x12/sd.png deleted file mode 100644 index 46d235ebf..000000000 Binary files a/pixmaps/flags18x12/sd.png and /dev/null differ diff --git a/pixmaps/flags18x12/se.png b/pixmaps/flags18x12/se.png deleted file mode 100644 index 1e13d4aee..000000000 Binary files a/pixmaps/flags18x12/se.png and /dev/null differ diff --git a/pixmaps/flags18x12/sg.png b/pixmaps/flags18x12/sg.png deleted file mode 100644 index e51d426c1..000000000 Binary files a/pixmaps/flags18x12/sg.png and /dev/null differ diff --git a/pixmaps/flags18x12/sh.png b/pixmaps/flags18x12/sh.png deleted file mode 100644 index c696327f6..000000000 Binary files a/pixmaps/flags18x12/sh.png and /dev/null differ diff --git a/pixmaps/flags18x12/si.png b/pixmaps/flags18x12/si.png deleted file mode 100644 index c278182d1..000000000 Binary files a/pixmaps/flags18x12/si.png and /dev/null differ diff --git a/pixmaps/flags18x12/sj.png b/pixmaps/flags18x12/sj.png deleted file mode 100644 index bac14bc40..000000000 Binary files a/pixmaps/flags18x12/sj.png and /dev/null differ diff --git a/pixmaps/flags18x12/sk.png b/pixmaps/flags18x12/sk.png deleted file mode 100644 index 2ee304725..000000000 Binary files a/pixmaps/flags18x12/sk.png and /dev/null differ diff --git a/pixmaps/flags18x12/sl.png b/pixmaps/flags18x12/sl.png deleted file mode 100644 index 40d2755de..000000000 Binary files a/pixmaps/flags18x12/sl.png and /dev/null differ diff --git a/pixmaps/flags18x12/sm.png b/pixmaps/flags18x12/sm.png deleted file mode 100644 index fe0cace00..000000000 Binary files a/pixmaps/flags18x12/sm.png and /dev/null differ diff --git a/pixmaps/flags18x12/sn.png b/pixmaps/flags18x12/sn.png deleted file mode 100644 index e3edef72c..000000000 Binary files a/pixmaps/flags18x12/sn.png and /dev/null differ diff --git a/pixmaps/flags18x12/so.png b/pixmaps/flags18x12/so.png deleted file mode 100644 index 915c224d4..000000000 Binary files a/pixmaps/flags18x12/so.png and /dev/null differ diff --git a/pixmaps/flags18x12/sr.png b/pixmaps/flags18x12/sr.png deleted file mode 100644 index 8ccf0c1c9..000000000 Binary files a/pixmaps/flags18x12/sr.png and /dev/null differ diff --git a/pixmaps/flags18x12/st.png b/pixmaps/flags18x12/st.png deleted file mode 100644 index c83b44c5f..000000000 Binary files a/pixmaps/flags18x12/st.png and /dev/null differ diff --git a/pixmaps/flags18x12/sv.png b/pixmaps/flags18x12/sv.png deleted file mode 100644 index f6e2c2fe5..000000000 Binary files a/pixmaps/flags18x12/sv.png and /dev/null differ diff --git a/pixmaps/flags18x12/sy.png b/pixmaps/flags18x12/sy.png deleted file mode 100644 index 9f2dc3ecb..000000000 Binary files a/pixmaps/flags18x12/sy.png and /dev/null differ diff --git a/pixmaps/flags18x12/sz.png b/pixmaps/flags18x12/sz.png deleted file mode 100644 index c880f713e..000000000 Binary files a/pixmaps/flags18x12/sz.png and /dev/null differ diff --git a/pixmaps/flags18x12/tc.png b/pixmaps/flags18x12/tc.png deleted file mode 100644 index b7450dec7..000000000 Binary files a/pixmaps/flags18x12/tc.png and /dev/null differ diff --git a/pixmaps/flags18x12/td.png b/pixmaps/flags18x12/td.png deleted file mode 100644 index cf8e057dd..000000000 Binary files a/pixmaps/flags18x12/td.png and /dev/null differ diff --git a/pixmaps/flags18x12/tf.png b/pixmaps/flags18x12/tf.png deleted file mode 100644 index 88d215861..000000000 Binary files a/pixmaps/flags18x12/tf.png and /dev/null differ diff --git a/pixmaps/flags18x12/tg.png b/pixmaps/flags18x12/tg.png deleted file mode 100644 index c9298dfa6..000000000 Binary files a/pixmaps/flags18x12/tg.png and /dev/null differ diff --git a/pixmaps/flags18x12/th.png b/pixmaps/flags18x12/th.png deleted file mode 100644 index e04583c32..000000000 Binary files a/pixmaps/flags18x12/th.png and /dev/null differ diff --git a/pixmaps/flags18x12/tj.png b/pixmaps/flags18x12/tj.png deleted file mode 100644 index efad9a5d2..000000000 Binary files a/pixmaps/flags18x12/tj.png and /dev/null differ diff --git a/pixmaps/flags18x12/tk.png b/pixmaps/flags18x12/tk.png deleted file mode 100644 index 36a08b14d..000000000 Binary files a/pixmaps/flags18x12/tk.png and /dev/null differ diff --git a/pixmaps/flags18x12/tl.png b/pixmaps/flags18x12/tl.png deleted file mode 100644 index b5df531ad..000000000 Binary files a/pixmaps/flags18x12/tl.png and /dev/null differ diff --git a/pixmaps/flags18x12/tm.png b/pixmaps/flags18x12/tm.png deleted file mode 100644 index aff8f4ed4..000000000 Binary files a/pixmaps/flags18x12/tm.png and /dev/null differ diff --git a/pixmaps/flags18x12/tn.png b/pixmaps/flags18x12/tn.png deleted file mode 100644 index 12e204509..000000000 Binary files a/pixmaps/flags18x12/tn.png and /dev/null differ diff --git a/pixmaps/flags18x12/to.png b/pixmaps/flags18x12/to.png deleted file mode 100644 index 5398fab5f..000000000 Binary files a/pixmaps/flags18x12/to.png and /dev/null differ diff --git a/pixmaps/flags18x12/tr.png b/pixmaps/flags18x12/tr.png deleted file mode 100644 index 66b0e45b5..000000000 Binary files a/pixmaps/flags18x12/tr.png and /dev/null differ diff --git a/pixmaps/flags18x12/tt.png b/pixmaps/flags18x12/tt.png deleted file mode 100644 index b3e16640e..000000000 Binary files a/pixmaps/flags18x12/tt.png and /dev/null differ diff --git a/pixmaps/flags18x12/tv.png b/pixmaps/flags18x12/tv.png deleted file mode 100644 index f78c0d9a1..000000000 Binary files a/pixmaps/flags18x12/tv.png and /dev/null differ diff --git a/pixmaps/flags18x12/tw.png b/pixmaps/flags18x12/tw.png deleted file mode 100644 index 2bb14c468..000000000 Binary files a/pixmaps/flags18x12/tw.png and /dev/null differ diff --git a/pixmaps/flags18x12/tz.png b/pixmaps/flags18x12/tz.png deleted file mode 100644 index f3e8e121f..000000000 Binary files a/pixmaps/flags18x12/tz.png and /dev/null differ diff --git a/pixmaps/flags18x12/ua.png b/pixmaps/flags18x12/ua.png deleted file mode 100644 index 86291367d..000000000 Binary files a/pixmaps/flags18x12/ua.png and /dev/null differ diff --git a/pixmaps/flags18x12/ug.png b/pixmaps/flags18x12/ug.png deleted file mode 100644 index d17a5d35a..000000000 Binary files a/pixmaps/flags18x12/ug.png and /dev/null differ diff --git a/pixmaps/flags18x12/um.png b/pixmaps/flags18x12/um.png deleted file mode 100644 index a21bdc56c..000000000 Binary files a/pixmaps/flags18x12/um.png and /dev/null differ diff --git a/pixmaps/flags18x12/us.png b/pixmaps/flags18x12/us.png deleted file mode 100644 index a21bdc56c..000000000 Binary files a/pixmaps/flags18x12/us.png and /dev/null differ diff --git a/pixmaps/flags18x12/uy.png b/pixmaps/flags18x12/uy.png deleted file mode 100644 index 43a2372e2..000000000 Binary files a/pixmaps/flags18x12/uy.png and /dev/null differ diff --git a/pixmaps/flags18x12/uz.png b/pixmaps/flags18x12/uz.png deleted file mode 100644 index 456d35927..000000000 Binary files a/pixmaps/flags18x12/uz.png and /dev/null differ diff --git a/pixmaps/flags18x12/va.png b/pixmaps/flags18x12/va.png deleted file mode 100644 index 306dc1ef5..000000000 Binary files a/pixmaps/flags18x12/va.png and /dev/null differ diff --git a/pixmaps/flags18x12/vc.png b/pixmaps/flags18x12/vc.png deleted file mode 100644 index 682471224..000000000 Binary files a/pixmaps/flags18x12/vc.png and /dev/null differ diff --git a/pixmaps/flags18x12/ve.png b/pixmaps/flags18x12/ve.png deleted file mode 100644 index c93b6fcdc..000000000 Binary files a/pixmaps/flags18x12/ve.png and /dev/null differ diff --git a/pixmaps/flags18x12/vg.png b/pixmaps/flags18x12/vg.png deleted file mode 100644 index 96172adda..000000000 Binary files a/pixmaps/flags18x12/vg.png and /dev/null differ diff --git a/pixmaps/flags18x12/vi.png b/pixmaps/flags18x12/vi.png deleted file mode 100644 index ab242df15..000000000 Binary files a/pixmaps/flags18x12/vi.png and /dev/null differ diff --git a/pixmaps/flags18x12/vn.png b/pixmaps/flags18x12/vn.png deleted file mode 100644 index d346b244c..000000000 Binary files a/pixmaps/flags18x12/vn.png and /dev/null differ diff --git a/pixmaps/flags18x12/vu.png b/pixmaps/flags18x12/vu.png deleted file mode 100644 index 4962e7bd2..000000000 Binary files a/pixmaps/flags18x12/vu.png and /dev/null differ diff --git a/pixmaps/flags18x12/wf.png b/pixmaps/flags18x12/wf.png deleted file mode 100644 index d4616ed1f..000000000 Binary files a/pixmaps/flags18x12/wf.png and /dev/null differ diff --git a/pixmaps/flags18x12/ws.png b/pixmaps/flags18x12/ws.png deleted file mode 100644 index 90c97c47d..000000000 Binary files a/pixmaps/flags18x12/ws.png and /dev/null differ diff --git a/pixmaps/flags18x12/ye.png b/pixmaps/flags18x12/ye.png deleted file mode 100644 index 8f3b8d22b..000000000 Binary files a/pixmaps/flags18x12/ye.png and /dev/null differ diff --git a/pixmaps/flags18x12/yt.png b/pixmaps/flags18x12/yt.png deleted file mode 100644 index d4616ed1f..000000000 Binary files a/pixmaps/flags18x12/yt.png and /dev/null differ diff --git a/pixmaps/flags18x12/za.png b/pixmaps/flags18x12/za.png deleted file mode 100644 index 490f2daec..000000000 Binary files a/pixmaps/flags18x12/za.png and /dev/null differ diff --git a/pixmaps/flags18x12/zm.png b/pixmaps/flags18x12/zm.png deleted file mode 100644 index 4fe4cbe03..000000000 Binary files a/pixmaps/flags18x12/zm.png and /dev/null differ diff --git a/pixmaps/flags18x12/zw.png b/pixmaps/flags18x12/zw.png deleted file mode 100644 index e7754fa38..000000000 Binary files a/pixmaps/flags18x12/zw.png and /dev/null differ diff --git a/pixmaps/flags25x15/FLAGS_LICENCE b/pixmaps/flags25x15/FLAGS_LICENCE deleted file mode 100644 index 368a8fef8..000000000 --- a/pixmaps/flags25x15/FLAGS_LICENCE +++ /dev/null @@ -1,2 +0,0 @@ -Flag images found at http://www.hahn-hotel.com/flags/ -"All sets provided by us are free to use to anyone, for commercial or non-commercial websites." \ No newline at end of file diff --git a/pixmaps/flags25x15/ad.png b/pixmaps/flags25x15/ad.png deleted file mode 100644 index 5d1720225..000000000 Binary files a/pixmaps/flags25x15/ad.png and /dev/null differ diff --git a/pixmaps/flags25x15/ae.png b/pixmaps/flags25x15/ae.png deleted file mode 100644 index 007dc36a7..000000000 Binary files a/pixmaps/flags25x15/ae.png and /dev/null differ diff --git a/pixmaps/flags25x15/af.png b/pixmaps/flags25x15/af.png deleted file mode 100644 index 9f9cd77e2..000000000 Binary files a/pixmaps/flags25x15/af.png and /dev/null differ diff --git a/pixmaps/flags25x15/ag.png b/pixmaps/flags25x15/ag.png deleted file mode 100644 index de7b76c10..000000000 Binary files a/pixmaps/flags25x15/ag.png and /dev/null differ diff --git a/pixmaps/flags25x15/ai.png b/pixmaps/flags25x15/ai.png deleted file mode 100644 index bbbd7b197..000000000 Binary files a/pixmaps/flags25x15/ai.png and /dev/null differ diff --git a/pixmaps/flags25x15/al.png b/pixmaps/flags25x15/al.png deleted file mode 100644 index c5d218cfa..000000000 Binary files a/pixmaps/flags25x15/al.png and /dev/null differ diff --git a/pixmaps/flags25x15/am.png b/pixmaps/flags25x15/am.png deleted file mode 100644 index 515451682..000000000 Binary files a/pixmaps/flags25x15/am.png and /dev/null differ diff --git a/pixmaps/flags25x15/an.png b/pixmaps/flags25x15/an.png deleted file mode 100644 index 28d1f98b3..000000000 Binary files a/pixmaps/flags25x15/an.png and /dev/null differ diff --git a/pixmaps/flags25x15/ao.png b/pixmaps/flags25x15/ao.png deleted file mode 100644 index 9dc5ab7cd..000000000 Binary files a/pixmaps/flags25x15/ao.png and /dev/null differ diff --git a/pixmaps/flags25x15/aq.png b/pixmaps/flags25x15/aq.png deleted file mode 100644 index 7caeae0ac..000000000 Binary files a/pixmaps/flags25x15/aq.png and /dev/null differ diff --git a/pixmaps/flags25x15/ar.png b/pixmaps/flags25x15/ar.png deleted file mode 100644 index dcabc83ce..000000000 Binary files a/pixmaps/flags25x15/ar.png and /dev/null differ diff --git a/pixmaps/flags25x15/as.png b/pixmaps/flags25x15/as.png deleted file mode 100644 index d19870923..000000000 Binary files a/pixmaps/flags25x15/as.png and /dev/null differ diff --git a/pixmaps/flags25x15/at.png b/pixmaps/flags25x15/at.png deleted file mode 100644 index fadb6a2e2..000000000 Binary files a/pixmaps/flags25x15/at.png and /dev/null differ diff --git a/pixmaps/flags25x15/au.png b/pixmaps/flags25x15/au.png deleted file mode 100644 index c8b559976..000000000 Binary files a/pixmaps/flags25x15/au.png and /dev/null differ diff --git a/pixmaps/flags25x15/aw.png b/pixmaps/flags25x15/aw.png deleted file mode 100644 index c66e1f1c4..000000000 Binary files a/pixmaps/flags25x15/aw.png and /dev/null differ diff --git a/pixmaps/flags25x15/ax.png b/pixmaps/flags25x15/ax.png deleted file mode 100644 index 917ff47db..000000000 Binary files a/pixmaps/flags25x15/ax.png and /dev/null differ diff --git a/pixmaps/flags25x15/az.png b/pixmaps/flags25x15/az.png deleted file mode 100644 index 381598aae..000000000 Binary files a/pixmaps/flags25x15/az.png and /dev/null differ diff --git a/pixmaps/flags25x15/ba.png b/pixmaps/flags25x15/ba.png deleted file mode 100644 index 6eff4f0dd..000000000 Binary files a/pixmaps/flags25x15/ba.png and /dev/null differ diff --git a/pixmaps/flags25x15/bb.png b/pixmaps/flags25x15/bb.png deleted file mode 100644 index 18a1e0ddc..000000000 Binary files a/pixmaps/flags25x15/bb.png and /dev/null differ diff --git a/pixmaps/flags25x15/bd.png b/pixmaps/flags25x15/bd.png deleted file mode 100644 index 00770ad1f..000000000 Binary files a/pixmaps/flags25x15/bd.png and /dev/null differ diff --git a/pixmaps/flags25x15/be.png b/pixmaps/flags25x15/be.png deleted file mode 100644 index b09b3d6c6..000000000 Binary files a/pixmaps/flags25x15/be.png and /dev/null differ diff --git a/pixmaps/flags25x15/bf.png b/pixmaps/flags25x15/bf.png deleted file mode 100644 index fc472787a..000000000 Binary files a/pixmaps/flags25x15/bf.png and /dev/null differ diff --git a/pixmaps/flags25x15/bg.png b/pixmaps/flags25x15/bg.png deleted file mode 100644 index d92441bda..000000000 Binary files a/pixmaps/flags25x15/bg.png and /dev/null differ diff --git a/pixmaps/flags25x15/bh.png b/pixmaps/flags25x15/bh.png deleted file mode 100644 index 4f6d433ef..000000000 Binary files a/pixmaps/flags25x15/bh.png and /dev/null differ diff --git a/pixmaps/flags25x15/bi.png b/pixmaps/flags25x15/bi.png deleted file mode 100644 index 3832f22a1..000000000 Binary files a/pixmaps/flags25x15/bi.png and /dev/null differ diff --git a/pixmaps/flags25x15/bj.png b/pixmaps/flags25x15/bj.png deleted file mode 100644 index dd3c6883e..000000000 Binary files a/pixmaps/flags25x15/bj.png and /dev/null differ diff --git a/pixmaps/flags25x15/bm.png b/pixmaps/flags25x15/bm.png deleted file mode 100644 index 1ec8e4383..000000000 Binary files a/pixmaps/flags25x15/bm.png and /dev/null differ diff --git a/pixmaps/flags25x15/bn.png b/pixmaps/flags25x15/bn.png deleted file mode 100644 index d8a6875d4..000000000 Binary files a/pixmaps/flags25x15/bn.png and /dev/null differ diff --git a/pixmaps/flags25x15/bo.png b/pixmaps/flags25x15/bo.png deleted file mode 100644 index c8686b529..000000000 Binary files a/pixmaps/flags25x15/bo.png and /dev/null differ diff --git a/pixmaps/flags25x15/br.png b/pixmaps/flags25x15/br.png deleted file mode 100644 index 22a98684c..000000000 Binary files a/pixmaps/flags25x15/br.png and /dev/null differ diff --git a/pixmaps/flags25x15/bs.png b/pixmaps/flags25x15/bs.png deleted file mode 100644 index dce7bcfae..000000000 Binary files a/pixmaps/flags25x15/bs.png and /dev/null differ diff --git a/pixmaps/flags25x15/bt.png b/pixmaps/flags25x15/bt.png deleted file mode 100644 index b87008a54..000000000 Binary files a/pixmaps/flags25x15/bt.png and /dev/null differ diff --git a/pixmaps/flags25x15/bv.png b/pixmaps/flags25x15/bv.png deleted file mode 100644 index 3f24fb54b..000000000 Binary files a/pixmaps/flags25x15/bv.png and /dev/null differ diff --git a/pixmaps/flags25x15/bw.png b/pixmaps/flags25x15/bw.png deleted file mode 100644 index 46a79b45c..000000000 Binary files a/pixmaps/flags25x15/bw.png and /dev/null differ diff --git a/pixmaps/flags25x15/by.png b/pixmaps/flags25x15/by.png deleted file mode 100644 index 030b0f6b9..000000000 Binary files a/pixmaps/flags25x15/by.png and /dev/null differ diff --git a/pixmaps/flags25x15/bz.png b/pixmaps/flags25x15/bz.png deleted file mode 100644 index 7ee942ea0..000000000 Binary files a/pixmaps/flags25x15/bz.png and /dev/null differ diff --git a/pixmaps/flags25x15/ca.png b/pixmaps/flags25x15/ca.png deleted file mode 100644 index d08962de0..000000000 Binary files a/pixmaps/flags25x15/ca.png and /dev/null differ diff --git a/pixmaps/flags25x15/cc.png b/pixmaps/flags25x15/cc.png deleted file mode 100644 index 18f219429..000000000 Binary files a/pixmaps/flags25x15/cc.png and /dev/null differ diff --git a/pixmaps/flags25x15/cd.png b/pixmaps/flags25x15/cd.png deleted file mode 100644 index 4adc67899..000000000 Binary files a/pixmaps/flags25x15/cd.png and /dev/null differ diff --git a/pixmaps/flags25x15/cf.png b/pixmaps/flags25x15/cf.png deleted file mode 100644 index f136158df..000000000 Binary files a/pixmaps/flags25x15/cf.png and /dev/null differ diff --git a/pixmaps/flags25x15/cg.png b/pixmaps/flags25x15/cg.png deleted file mode 100644 index 2ec7d0e8b..000000000 Binary files a/pixmaps/flags25x15/cg.png and /dev/null differ diff --git a/pixmaps/flags25x15/ch.png b/pixmaps/flags25x15/ch.png deleted file mode 100644 index e8b1cfcf7..000000000 Binary files a/pixmaps/flags25x15/ch.png and /dev/null differ diff --git a/pixmaps/flags25x15/ci.png b/pixmaps/flags25x15/ci.png deleted file mode 100644 index c7644cb76..000000000 Binary files a/pixmaps/flags25x15/ci.png and /dev/null differ diff --git a/pixmaps/flags25x15/ck.png b/pixmaps/flags25x15/ck.png deleted file mode 100644 index a896cc24e..000000000 Binary files a/pixmaps/flags25x15/ck.png and /dev/null differ diff --git a/pixmaps/flags25x15/cl.png b/pixmaps/flags25x15/cl.png deleted file mode 100644 index a113a2b3c..000000000 Binary files a/pixmaps/flags25x15/cl.png and /dev/null differ diff --git a/pixmaps/flags25x15/cm.png b/pixmaps/flags25x15/cm.png deleted file mode 100644 index a5d828f1b..000000000 Binary files a/pixmaps/flags25x15/cm.png and /dev/null differ diff --git a/pixmaps/flags25x15/cn.png b/pixmaps/flags25x15/cn.png deleted file mode 100644 index 2ad03f6d4..000000000 Binary files a/pixmaps/flags25x15/cn.png and /dev/null differ diff --git a/pixmaps/flags25x15/co.png b/pixmaps/flags25x15/co.png deleted file mode 100644 index 362f006fb..000000000 Binary files a/pixmaps/flags25x15/co.png and /dev/null differ diff --git a/pixmaps/flags25x15/cr.png b/pixmaps/flags25x15/cr.png deleted file mode 100644 index a184a8dc7..000000000 Binary files a/pixmaps/flags25x15/cr.png and /dev/null differ diff --git a/pixmaps/flags25x15/cs.png b/pixmaps/flags25x15/cs.png deleted file mode 100644 index 7a89a78c1..000000000 Binary files a/pixmaps/flags25x15/cs.png and /dev/null differ diff --git a/pixmaps/flags25x15/cu.png b/pixmaps/flags25x15/cu.png deleted file mode 100644 index 19c6f800d..000000000 Binary files a/pixmaps/flags25x15/cu.png and /dev/null differ diff --git a/pixmaps/flags25x15/cv.png b/pixmaps/flags25x15/cv.png deleted file mode 100644 index 4f6bf243c..000000000 Binary files a/pixmaps/flags25x15/cv.png and /dev/null differ diff --git a/pixmaps/flags25x15/cx.png b/pixmaps/flags25x15/cx.png deleted file mode 100644 index 5c858cac7..000000000 Binary files a/pixmaps/flags25x15/cx.png and /dev/null differ diff --git a/pixmaps/flags25x15/cy.png b/pixmaps/flags25x15/cy.png deleted file mode 100644 index 8b03f5181..000000000 Binary files a/pixmaps/flags25x15/cy.png and /dev/null differ diff --git a/pixmaps/flags25x15/cz.png b/pixmaps/flags25x15/cz.png deleted file mode 100644 index 97ed7e846..000000000 Binary files a/pixmaps/flags25x15/cz.png and /dev/null differ diff --git a/pixmaps/flags25x15/de.png b/pixmaps/flags25x15/de.png deleted file mode 100644 index 24b07b581..000000000 Binary files a/pixmaps/flags25x15/de.png and /dev/null differ diff --git a/pixmaps/flags25x15/dj.png b/pixmaps/flags25x15/dj.png deleted file mode 100644 index 791c251d5..000000000 Binary files a/pixmaps/flags25x15/dj.png and /dev/null differ diff --git a/pixmaps/flags25x15/dk.png b/pixmaps/flags25x15/dk.png deleted file mode 100644 index 2be6ab1b0..000000000 Binary files a/pixmaps/flags25x15/dk.png and /dev/null differ diff --git a/pixmaps/flags25x15/dm.png b/pixmaps/flags25x15/dm.png deleted file mode 100644 index edd7fff0e..000000000 Binary files a/pixmaps/flags25x15/dm.png and /dev/null differ diff --git a/pixmaps/flags25x15/do.png b/pixmaps/flags25x15/do.png deleted file mode 100644 index 622276206..000000000 Binary files a/pixmaps/flags25x15/do.png and /dev/null differ diff --git a/pixmaps/flags25x15/dz.png b/pixmaps/flags25x15/dz.png deleted file mode 100644 index 743cb1f62..000000000 Binary files a/pixmaps/flags25x15/dz.png and /dev/null differ diff --git a/pixmaps/flags25x15/ec.png b/pixmaps/flags25x15/ec.png deleted file mode 100644 index cb87ce832..000000000 Binary files a/pixmaps/flags25x15/ec.png and /dev/null differ diff --git a/pixmaps/flags25x15/ee.png b/pixmaps/flags25x15/ee.png deleted file mode 100644 index 94e5106ff..000000000 Binary files a/pixmaps/flags25x15/ee.png and /dev/null differ diff --git a/pixmaps/flags25x15/eg.png b/pixmaps/flags25x15/eg.png deleted file mode 100644 index dba11a2a7..000000000 Binary files a/pixmaps/flags25x15/eg.png and /dev/null differ diff --git a/pixmaps/flags25x15/eh.png b/pixmaps/flags25x15/eh.png deleted file mode 100644 index 1512a322b..000000000 Binary files a/pixmaps/flags25x15/eh.png and /dev/null differ diff --git a/pixmaps/flags25x15/er.png b/pixmaps/flags25x15/er.png deleted file mode 100644 index 43225fa62..000000000 Binary files a/pixmaps/flags25x15/er.png and /dev/null differ diff --git a/pixmaps/flags25x15/es.png b/pixmaps/flags25x15/es.png deleted file mode 100644 index 4b30c49f2..000000000 Binary files a/pixmaps/flags25x15/es.png and /dev/null differ diff --git a/pixmaps/flags25x15/et.png b/pixmaps/flags25x15/et.png deleted file mode 100644 index 7275abf09..000000000 Binary files a/pixmaps/flags25x15/et.png and /dev/null differ diff --git a/pixmaps/flags25x15/fi.png b/pixmaps/flags25x15/fi.png deleted file mode 100644 index 8574dec77..000000000 Binary files a/pixmaps/flags25x15/fi.png and /dev/null differ diff --git a/pixmaps/flags25x15/fj.png b/pixmaps/flags25x15/fj.png deleted file mode 100644 index dd021d5ae..000000000 Binary files a/pixmaps/flags25x15/fj.png and /dev/null differ diff --git a/pixmaps/flags25x15/fk.png b/pixmaps/flags25x15/fk.png deleted file mode 100644 index 7c277bc57..000000000 Binary files a/pixmaps/flags25x15/fk.png and /dev/null differ diff --git a/pixmaps/flags25x15/fm.png b/pixmaps/flags25x15/fm.png deleted file mode 100644 index 6c4e13794..000000000 Binary files a/pixmaps/flags25x15/fm.png and /dev/null differ diff --git a/pixmaps/flags25x15/fo.png b/pixmaps/flags25x15/fo.png deleted file mode 100644 index 8eeb7ccc7..000000000 Binary files a/pixmaps/flags25x15/fo.png and /dev/null differ diff --git a/pixmaps/flags25x15/fr.png b/pixmaps/flags25x15/fr.png deleted file mode 100644 index c1a539549..000000000 Binary files a/pixmaps/flags25x15/fr.png and /dev/null differ diff --git a/pixmaps/flags25x15/fx.png b/pixmaps/flags25x15/fx.png deleted file mode 100644 index c1a539549..000000000 Binary files a/pixmaps/flags25x15/fx.png and /dev/null differ diff --git a/pixmaps/flags25x15/ga.png b/pixmaps/flags25x15/ga.png deleted file mode 100644 index 9c72bec54..000000000 Binary files a/pixmaps/flags25x15/ga.png and /dev/null differ diff --git a/pixmaps/flags25x15/gb.png b/pixmaps/flags25x15/gb.png deleted file mode 100644 index 8558aa61b..000000000 Binary files a/pixmaps/flags25x15/gb.png and /dev/null differ diff --git a/pixmaps/flags25x15/gd.png b/pixmaps/flags25x15/gd.png deleted file mode 100644 index 753538162..000000000 Binary files a/pixmaps/flags25x15/gd.png and /dev/null differ diff --git a/pixmaps/flags25x15/ge.png b/pixmaps/flags25x15/ge.png deleted file mode 100644 index 847e89d52..000000000 Binary files a/pixmaps/flags25x15/ge.png and /dev/null differ diff --git a/pixmaps/flags25x15/gf.png b/pixmaps/flags25x15/gf.png deleted file mode 100644 index c1a539549..000000000 Binary files a/pixmaps/flags25x15/gf.png and /dev/null differ diff --git a/pixmaps/flags25x15/gg.png b/pixmaps/flags25x15/gg.png deleted file mode 100644 index cef5a7ee1..000000000 Binary files a/pixmaps/flags25x15/gg.png and /dev/null differ diff --git a/pixmaps/flags25x15/gh.png b/pixmaps/flags25x15/gh.png deleted file mode 100644 index f9aa766f5..000000000 Binary files a/pixmaps/flags25x15/gh.png and /dev/null differ diff --git a/pixmaps/flags25x15/gi.png b/pixmaps/flags25x15/gi.png deleted file mode 100644 index 5de3e79f4..000000000 Binary files a/pixmaps/flags25x15/gi.png and /dev/null differ diff --git a/pixmaps/flags25x15/gl.png b/pixmaps/flags25x15/gl.png deleted file mode 100644 index f10fc56b3..000000000 Binary files a/pixmaps/flags25x15/gl.png and /dev/null differ diff --git a/pixmaps/flags25x15/gm.png b/pixmaps/flags25x15/gm.png deleted file mode 100644 index c09dc7978..000000000 Binary files a/pixmaps/flags25x15/gm.png and /dev/null differ diff --git a/pixmaps/flags25x15/gn.png b/pixmaps/flags25x15/gn.png deleted file mode 100644 index 99748b520..000000000 Binary files a/pixmaps/flags25x15/gn.png and /dev/null differ diff --git a/pixmaps/flags25x15/gp.png b/pixmaps/flags25x15/gp.png deleted file mode 100644 index c1a539549..000000000 Binary files a/pixmaps/flags25x15/gp.png and /dev/null differ diff --git a/pixmaps/flags25x15/gq.png b/pixmaps/flags25x15/gq.png deleted file mode 100644 index 14c8b43c8..000000000 Binary files a/pixmaps/flags25x15/gq.png and /dev/null differ diff --git a/pixmaps/flags25x15/gr.png b/pixmaps/flags25x15/gr.png deleted file mode 100644 index 35871f058..000000000 Binary files a/pixmaps/flags25x15/gr.png and /dev/null differ diff --git a/pixmaps/flags25x15/gs.png b/pixmaps/flags25x15/gs.png deleted file mode 100644 index 700656b2c..000000000 Binary files a/pixmaps/flags25x15/gs.png and /dev/null differ diff --git a/pixmaps/flags25x15/gt.png b/pixmaps/flags25x15/gt.png deleted file mode 100644 index e8cce5864..000000000 Binary files a/pixmaps/flags25x15/gt.png and /dev/null differ diff --git a/pixmaps/flags25x15/gu.png b/pixmaps/flags25x15/gu.png deleted file mode 100644 index 40ddc6840..000000000 Binary files a/pixmaps/flags25x15/gu.png and /dev/null differ diff --git a/pixmaps/flags25x15/gw.png b/pixmaps/flags25x15/gw.png deleted file mode 100644 index ec220ce45..000000000 Binary files a/pixmaps/flags25x15/gw.png and /dev/null differ diff --git a/pixmaps/flags25x15/gy.png b/pixmaps/flags25x15/gy.png deleted file mode 100644 index 2daa0968f..000000000 Binary files a/pixmaps/flags25x15/gy.png and /dev/null differ diff --git a/pixmaps/flags25x15/hk.png b/pixmaps/flags25x15/hk.png deleted file mode 100644 index a2eeca2eb..000000000 Binary files a/pixmaps/flags25x15/hk.png and /dev/null differ diff --git a/pixmaps/flags25x15/hm.png b/pixmaps/flags25x15/hm.png deleted file mode 100644 index c8b559976..000000000 Binary files a/pixmaps/flags25x15/hm.png and /dev/null differ diff --git a/pixmaps/flags25x15/hn.png b/pixmaps/flags25x15/hn.png deleted file mode 100644 index 633abb16a..000000000 Binary files a/pixmaps/flags25x15/hn.png and /dev/null differ diff --git a/pixmaps/flags25x15/hr.png b/pixmaps/flags25x15/hr.png deleted file mode 100644 index ba09f129b..000000000 Binary files a/pixmaps/flags25x15/hr.png and /dev/null differ diff --git a/pixmaps/flags25x15/ht.png b/pixmaps/flags25x15/ht.png deleted file mode 100644 index cf97344e3..000000000 Binary files a/pixmaps/flags25x15/ht.png and /dev/null differ diff --git a/pixmaps/flags25x15/hu.png b/pixmaps/flags25x15/hu.png deleted file mode 100644 index 3345bde6a..000000000 Binary files a/pixmaps/flags25x15/hu.png and /dev/null differ diff --git a/pixmaps/flags25x15/id.png b/pixmaps/flags25x15/id.png deleted file mode 100644 index 6aa9fde89..000000000 Binary files a/pixmaps/flags25x15/id.png and /dev/null differ diff --git a/pixmaps/flags25x15/ie.png b/pixmaps/flags25x15/ie.png deleted file mode 100644 index fe977c307..000000000 Binary files a/pixmaps/flags25x15/ie.png and /dev/null differ diff --git a/pixmaps/flags25x15/il.png b/pixmaps/flags25x15/il.png deleted file mode 100644 index bc8523eee..000000000 Binary files a/pixmaps/flags25x15/il.png and /dev/null differ diff --git a/pixmaps/flags25x15/in.png b/pixmaps/flags25x15/in.png deleted file mode 100644 index b7c54956c..000000000 Binary files a/pixmaps/flags25x15/in.png and /dev/null differ diff --git a/pixmaps/flags25x15/io.png b/pixmaps/flags25x15/io.png deleted file mode 100644 index fd5fb1cf4..000000000 Binary files a/pixmaps/flags25x15/io.png and /dev/null differ diff --git a/pixmaps/flags25x15/iq.png b/pixmaps/flags25x15/iq.png deleted file mode 100644 index 14a254dbf..000000000 Binary files a/pixmaps/flags25x15/iq.png and /dev/null differ diff --git a/pixmaps/flags25x15/ir.png b/pixmaps/flags25x15/ir.png deleted file mode 100644 index 4d7cb1f54..000000000 Binary files a/pixmaps/flags25x15/ir.png and /dev/null differ diff --git a/pixmaps/flags25x15/is.png b/pixmaps/flags25x15/is.png deleted file mode 100644 index aa9011425..000000000 Binary files a/pixmaps/flags25x15/is.png and /dev/null differ diff --git a/pixmaps/flags25x15/it.png b/pixmaps/flags25x15/it.png deleted file mode 100644 index 5212ade5f..000000000 Binary files a/pixmaps/flags25x15/it.png and /dev/null differ diff --git a/pixmaps/flags25x15/je.png b/pixmaps/flags25x15/je.png deleted file mode 100644 index 5930485ba..000000000 Binary files a/pixmaps/flags25x15/je.png and /dev/null differ diff --git a/pixmaps/flags25x15/jm.png b/pixmaps/flags25x15/jm.png deleted file mode 100644 index ccedfcda3..000000000 Binary files a/pixmaps/flags25x15/jm.png and /dev/null differ diff --git a/pixmaps/flags25x15/jo.png b/pixmaps/flags25x15/jo.png deleted file mode 100644 index f4332604b..000000000 Binary files a/pixmaps/flags25x15/jo.png and /dev/null differ diff --git a/pixmaps/flags25x15/jp.png b/pixmaps/flags25x15/jp.png deleted file mode 100644 index fb4f7573a..000000000 Binary files a/pixmaps/flags25x15/jp.png and /dev/null differ diff --git a/pixmaps/flags25x15/ke.png b/pixmaps/flags25x15/ke.png deleted file mode 100644 index 3538e8d2e..000000000 Binary files a/pixmaps/flags25x15/ke.png and /dev/null differ diff --git a/pixmaps/flags25x15/kg.png b/pixmaps/flags25x15/kg.png deleted file mode 100644 index 889b612b9..000000000 Binary files a/pixmaps/flags25x15/kg.png and /dev/null differ diff --git a/pixmaps/flags25x15/kh.png b/pixmaps/flags25x15/kh.png deleted file mode 100644 index 772f5870b..000000000 Binary files a/pixmaps/flags25x15/kh.png and /dev/null differ diff --git a/pixmaps/flags25x15/ki.png b/pixmaps/flags25x15/ki.png deleted file mode 100644 index 4c8a67c9d..000000000 Binary files a/pixmaps/flags25x15/ki.png and /dev/null differ diff --git a/pixmaps/flags25x15/km.png b/pixmaps/flags25x15/km.png deleted file mode 100644 index e704afb34..000000000 Binary files a/pixmaps/flags25x15/km.png and /dev/null differ diff --git a/pixmaps/flags25x15/kn.png b/pixmaps/flags25x15/kn.png deleted file mode 100644 index 042232c2d..000000000 Binary files a/pixmaps/flags25x15/kn.png and /dev/null differ diff --git a/pixmaps/flags25x15/kp.png b/pixmaps/flags25x15/kp.png deleted file mode 100644 index f8fbd308f..000000000 Binary files a/pixmaps/flags25x15/kp.png and /dev/null differ diff --git a/pixmaps/flags25x15/kr.png b/pixmaps/flags25x15/kr.png deleted file mode 100644 index f83ebb31e..000000000 Binary files a/pixmaps/flags25x15/kr.png and /dev/null differ diff --git a/pixmaps/flags25x15/kw.png b/pixmaps/flags25x15/kw.png deleted file mode 100644 index 24748c6c3..000000000 Binary files a/pixmaps/flags25x15/kw.png and /dev/null differ diff --git a/pixmaps/flags25x15/ky.png b/pixmaps/flags25x15/ky.png deleted file mode 100644 index 697377161..000000000 Binary files a/pixmaps/flags25x15/ky.png and /dev/null differ diff --git a/pixmaps/flags25x15/kz.png b/pixmaps/flags25x15/kz.png deleted file mode 100644 index 3e102a414..000000000 Binary files a/pixmaps/flags25x15/kz.png and /dev/null differ diff --git a/pixmaps/flags25x15/la.png b/pixmaps/flags25x15/la.png deleted file mode 100644 index 532e3b679..000000000 Binary files a/pixmaps/flags25x15/la.png and /dev/null differ diff --git a/pixmaps/flags25x15/lb.png b/pixmaps/flags25x15/lb.png deleted file mode 100644 index 4f94e9f95..000000000 Binary files a/pixmaps/flags25x15/lb.png and /dev/null differ diff --git a/pixmaps/flags25x15/lc.png b/pixmaps/flags25x15/lc.png deleted file mode 100644 index a1205be94..000000000 Binary files a/pixmaps/flags25x15/lc.png and /dev/null differ diff --git a/pixmaps/flags25x15/li.png b/pixmaps/flags25x15/li.png deleted file mode 100644 index adef5a82d..000000000 Binary files a/pixmaps/flags25x15/li.png and /dev/null differ diff --git a/pixmaps/flags25x15/lk.png b/pixmaps/flags25x15/lk.png deleted file mode 100644 index 9ff43b5eb..000000000 Binary files a/pixmaps/flags25x15/lk.png and /dev/null differ diff --git a/pixmaps/flags25x15/lr.png b/pixmaps/flags25x15/lr.png deleted file mode 100644 index dc4c555b5..000000000 Binary files a/pixmaps/flags25x15/lr.png and /dev/null differ diff --git a/pixmaps/flags25x15/ls.png b/pixmaps/flags25x15/ls.png deleted file mode 100644 index 4e0a9b03d..000000000 Binary files a/pixmaps/flags25x15/ls.png and /dev/null differ diff --git a/pixmaps/flags25x15/lt.png b/pixmaps/flags25x15/lt.png deleted file mode 100644 index e951f7d80..000000000 Binary files a/pixmaps/flags25x15/lt.png and /dev/null differ diff --git a/pixmaps/flags25x15/lu.png b/pixmaps/flags25x15/lu.png deleted file mode 100644 index aba4a1073..000000000 Binary files a/pixmaps/flags25x15/lu.png and /dev/null differ diff --git a/pixmaps/flags25x15/lv.png b/pixmaps/flags25x15/lv.png deleted file mode 100644 index 992161558..000000000 Binary files a/pixmaps/flags25x15/lv.png and /dev/null differ diff --git a/pixmaps/flags25x15/ly.png b/pixmaps/flags25x15/ly.png deleted file mode 100644 index 55f5edd50..000000000 Binary files a/pixmaps/flags25x15/ly.png and /dev/null differ diff --git a/pixmaps/flags25x15/ma.png b/pixmaps/flags25x15/ma.png deleted file mode 100644 index f6f9d1fef..000000000 Binary files a/pixmaps/flags25x15/ma.png and /dev/null differ diff --git a/pixmaps/flags25x15/mc.png b/pixmaps/flags25x15/mc.png deleted file mode 100644 index 05b3bb480..000000000 Binary files a/pixmaps/flags25x15/mc.png and /dev/null differ diff --git a/pixmaps/flags25x15/md.png b/pixmaps/flags25x15/md.png deleted file mode 100644 index 81c36fa1b..000000000 Binary files a/pixmaps/flags25x15/md.png and /dev/null differ diff --git a/pixmaps/flags25x15/me.png b/pixmaps/flags25x15/me.png deleted file mode 100644 index 5f5199ef4..000000000 Binary files a/pixmaps/flags25x15/me.png and /dev/null differ diff --git a/pixmaps/flags25x15/mg.png b/pixmaps/flags25x15/mg.png deleted file mode 100644 index ee2a02461..000000000 Binary files a/pixmaps/flags25x15/mg.png and /dev/null differ diff --git a/pixmaps/flags25x15/mh.png b/pixmaps/flags25x15/mh.png deleted file mode 100644 index 00af51fb6..000000000 Binary files a/pixmaps/flags25x15/mh.png and /dev/null differ diff --git a/pixmaps/flags25x15/mk.png b/pixmaps/flags25x15/mk.png deleted file mode 100644 index 618475d22..000000000 Binary files a/pixmaps/flags25x15/mk.png and /dev/null differ diff --git a/pixmaps/flags25x15/ml.png b/pixmaps/flags25x15/ml.png deleted file mode 100644 index b10bcac64..000000000 Binary files a/pixmaps/flags25x15/ml.png and /dev/null differ diff --git a/pixmaps/flags25x15/mm.png b/pixmaps/flags25x15/mm.png deleted file mode 100644 index f96999501..000000000 Binary files a/pixmaps/flags25x15/mm.png and /dev/null differ diff --git a/pixmaps/flags25x15/mn.png b/pixmaps/flags25x15/mn.png deleted file mode 100644 index 2a824d55f..000000000 Binary files a/pixmaps/flags25x15/mn.png and /dev/null differ diff --git a/pixmaps/flags25x15/mo.png b/pixmaps/flags25x15/mo.png deleted file mode 100644 index 06a1ead9a..000000000 Binary files a/pixmaps/flags25x15/mo.png and /dev/null differ diff --git a/pixmaps/flags25x15/mp.png b/pixmaps/flags25x15/mp.png deleted file mode 100644 index 52625e3d4..000000000 Binary files a/pixmaps/flags25x15/mp.png and /dev/null differ diff --git a/pixmaps/flags25x15/mq.png b/pixmaps/flags25x15/mq.png deleted file mode 100644 index c1a539549..000000000 Binary files a/pixmaps/flags25x15/mq.png and /dev/null differ diff --git a/pixmaps/flags25x15/mr.png b/pixmaps/flags25x15/mr.png deleted file mode 100644 index 52fcfc229..000000000 Binary files a/pixmaps/flags25x15/mr.png and /dev/null differ diff --git a/pixmaps/flags25x15/ms.png b/pixmaps/flags25x15/ms.png deleted file mode 100644 index 022ca1a1a..000000000 Binary files a/pixmaps/flags25x15/ms.png and /dev/null differ diff --git a/pixmaps/flags25x15/mt.png b/pixmaps/flags25x15/mt.png deleted file mode 100644 index ada70c644..000000000 Binary files a/pixmaps/flags25x15/mt.png and /dev/null differ diff --git a/pixmaps/flags25x15/mu.png b/pixmaps/flags25x15/mu.png deleted file mode 100644 index 1126c7abb..000000000 Binary files a/pixmaps/flags25x15/mu.png and /dev/null differ diff --git a/pixmaps/flags25x15/mv.png b/pixmaps/flags25x15/mv.png deleted file mode 100644 index 8f12c5b36..000000000 Binary files a/pixmaps/flags25x15/mv.png and /dev/null differ diff --git a/pixmaps/flags25x15/mw.png b/pixmaps/flags25x15/mw.png deleted file mode 100644 index 1ff74952e..000000000 Binary files a/pixmaps/flags25x15/mw.png and /dev/null differ diff --git a/pixmaps/flags25x15/mx.png b/pixmaps/flags25x15/mx.png deleted file mode 100644 index 0d7c67142..000000000 Binary files a/pixmaps/flags25x15/mx.png and /dev/null differ diff --git a/pixmaps/flags25x15/my.png b/pixmaps/flags25x15/my.png deleted file mode 100644 index 4eead54bd..000000000 Binary files a/pixmaps/flags25x15/my.png and /dev/null differ diff --git a/pixmaps/flags25x15/mz.png b/pixmaps/flags25x15/mz.png deleted file mode 100644 index 10b4b8d2b..000000000 Binary files a/pixmaps/flags25x15/mz.png and /dev/null differ diff --git a/pixmaps/flags25x15/na.png b/pixmaps/flags25x15/na.png deleted file mode 100644 index db2580e8e..000000000 Binary files a/pixmaps/flags25x15/na.png and /dev/null differ diff --git a/pixmaps/flags25x15/nc.png b/pixmaps/flags25x15/nc.png deleted file mode 100644 index c1a539549..000000000 Binary files a/pixmaps/flags25x15/nc.png and /dev/null differ diff --git a/pixmaps/flags25x15/ne.png b/pixmaps/flags25x15/ne.png deleted file mode 100644 index fd818af33..000000000 Binary files a/pixmaps/flags25x15/ne.png and /dev/null differ diff --git a/pixmaps/flags25x15/nf.png b/pixmaps/flags25x15/nf.png deleted file mode 100644 index 46f61f0ad..000000000 Binary files a/pixmaps/flags25x15/nf.png and /dev/null differ diff --git a/pixmaps/flags25x15/ng.png b/pixmaps/flags25x15/ng.png deleted file mode 100644 index e61fcbb33..000000000 Binary files a/pixmaps/flags25x15/ng.png and /dev/null differ diff --git a/pixmaps/flags25x15/ni.png b/pixmaps/flags25x15/ni.png deleted file mode 100644 index 50bebdf15..000000000 Binary files a/pixmaps/flags25x15/ni.png and /dev/null differ diff --git a/pixmaps/flags25x15/nl.png b/pixmaps/flags25x15/nl.png deleted file mode 100644 index 08d2f2abb..000000000 Binary files a/pixmaps/flags25x15/nl.png and /dev/null differ diff --git a/pixmaps/flags25x15/no.png b/pixmaps/flags25x15/no.png deleted file mode 100644 index 3f24fb54b..000000000 Binary files a/pixmaps/flags25x15/no.png and /dev/null differ diff --git a/pixmaps/flags25x15/np.png b/pixmaps/flags25x15/np.png deleted file mode 100644 index f561629df..000000000 Binary files a/pixmaps/flags25x15/np.png and /dev/null differ diff --git a/pixmaps/flags25x15/nr.png b/pixmaps/flags25x15/nr.png deleted file mode 100644 index 15474be90..000000000 Binary files a/pixmaps/flags25x15/nr.png and /dev/null differ diff --git a/pixmaps/flags25x15/nu.png b/pixmaps/flags25x15/nu.png deleted file mode 100644 index fd9f9e032..000000000 Binary files a/pixmaps/flags25x15/nu.png and /dev/null differ diff --git a/pixmaps/flags25x15/nz.png b/pixmaps/flags25x15/nz.png deleted file mode 100644 index 5bcbefd91..000000000 Binary files a/pixmaps/flags25x15/nz.png and /dev/null differ diff --git a/pixmaps/flags25x15/om.png b/pixmaps/flags25x15/om.png deleted file mode 100644 index 01a3db1b1..000000000 Binary files a/pixmaps/flags25x15/om.png and /dev/null differ diff --git a/pixmaps/flags25x15/pa.png b/pixmaps/flags25x15/pa.png deleted file mode 100644 index 632bd8e6e..000000000 Binary files a/pixmaps/flags25x15/pa.png and /dev/null differ diff --git a/pixmaps/flags25x15/pe.png b/pixmaps/flags25x15/pe.png deleted file mode 100644 index c3b68310b..000000000 Binary files a/pixmaps/flags25x15/pe.png and /dev/null differ diff --git a/pixmaps/flags25x15/pf.png b/pixmaps/flags25x15/pf.png deleted file mode 100644 index c9eaf6d42..000000000 Binary files a/pixmaps/flags25x15/pf.png and /dev/null differ diff --git a/pixmaps/flags25x15/pg.png b/pixmaps/flags25x15/pg.png deleted file mode 100644 index 1aa244ebe..000000000 Binary files a/pixmaps/flags25x15/pg.png and /dev/null differ diff --git a/pixmaps/flags25x15/ph.png b/pixmaps/flags25x15/ph.png deleted file mode 100644 index bac753b58..000000000 Binary files a/pixmaps/flags25x15/ph.png and /dev/null differ diff --git a/pixmaps/flags25x15/pk.png b/pixmaps/flags25x15/pk.png deleted file mode 100644 index c77f3fd24..000000000 Binary files a/pixmaps/flags25x15/pk.png and /dev/null differ diff --git a/pixmaps/flags25x15/pl.png b/pixmaps/flags25x15/pl.png deleted file mode 100644 index 6c83c264a..000000000 Binary files a/pixmaps/flags25x15/pl.png and /dev/null differ diff --git a/pixmaps/flags25x15/pm.png b/pixmaps/flags25x15/pm.png deleted file mode 100644 index c1a539549..000000000 Binary files a/pixmaps/flags25x15/pm.png and /dev/null differ diff --git a/pixmaps/flags25x15/pn.png b/pixmaps/flags25x15/pn.png deleted file mode 100644 index 55f7b9150..000000000 Binary files a/pixmaps/flags25x15/pn.png and /dev/null differ diff --git a/pixmaps/flags25x15/pr.png b/pixmaps/flags25x15/pr.png deleted file mode 100644 index e12c95831..000000000 Binary files a/pixmaps/flags25x15/pr.png and /dev/null differ diff --git a/pixmaps/flags25x15/ps.png b/pixmaps/flags25x15/ps.png deleted file mode 100644 index fe3a67686..000000000 Binary files a/pixmaps/flags25x15/ps.png and /dev/null differ diff --git a/pixmaps/flags25x15/pt.png b/pixmaps/flags25x15/pt.png deleted file mode 100644 index 0911015a0..000000000 Binary files a/pixmaps/flags25x15/pt.png and /dev/null differ diff --git a/pixmaps/flags25x15/pw.png b/pixmaps/flags25x15/pw.png deleted file mode 100644 index 89e957275..000000000 Binary files a/pixmaps/flags25x15/pw.png and /dev/null differ diff --git a/pixmaps/flags25x15/py.png b/pixmaps/flags25x15/py.png deleted file mode 100644 index 78e16f1ad..000000000 Binary files a/pixmaps/flags25x15/py.png and /dev/null differ diff --git a/pixmaps/flags25x15/qa.png b/pixmaps/flags25x15/qa.png deleted file mode 100644 index 1e63f0482..000000000 Binary files a/pixmaps/flags25x15/qa.png and /dev/null differ diff --git a/pixmaps/flags25x15/re.png b/pixmaps/flags25x15/re.png deleted file mode 100644 index c1a539549..000000000 Binary files a/pixmaps/flags25x15/re.png and /dev/null differ diff --git a/pixmaps/flags25x15/ro.png b/pixmaps/flags25x15/ro.png deleted file mode 100644 index 4a4f7b589..000000000 Binary files a/pixmaps/flags25x15/ro.png and /dev/null differ diff --git a/pixmaps/flags25x15/rs.png b/pixmaps/flags25x15/rs.png deleted file mode 100644 index 28afdd597..000000000 Binary files a/pixmaps/flags25x15/rs.png and /dev/null differ diff --git a/pixmaps/flags25x15/ru.png b/pixmaps/flags25x15/ru.png deleted file mode 100644 index e6f8bb0eb..000000000 Binary files a/pixmaps/flags25x15/ru.png and /dev/null differ diff --git a/pixmaps/flags25x15/rw.png b/pixmaps/flags25x15/rw.png deleted file mode 100644 index 05543ea12..000000000 Binary files a/pixmaps/flags25x15/rw.png and /dev/null differ diff --git a/pixmaps/flags25x15/sa.png b/pixmaps/flags25x15/sa.png deleted file mode 100644 index a38fc791a..000000000 Binary files a/pixmaps/flags25x15/sa.png and /dev/null differ diff --git a/pixmaps/flags25x15/sb.png b/pixmaps/flags25x15/sb.png deleted file mode 100644 index f2748306a..000000000 Binary files a/pixmaps/flags25x15/sb.png and /dev/null differ diff --git a/pixmaps/flags25x15/sc.png b/pixmaps/flags25x15/sc.png deleted file mode 100644 index 369368ba6..000000000 Binary files a/pixmaps/flags25x15/sc.png and /dev/null differ diff --git a/pixmaps/flags25x15/sd.png b/pixmaps/flags25x15/sd.png deleted file mode 100644 index 54c57bf80..000000000 Binary files a/pixmaps/flags25x15/sd.png and /dev/null differ diff --git a/pixmaps/flags25x15/se.png b/pixmaps/flags25x15/se.png deleted file mode 100644 index 0b7156f70..000000000 Binary files a/pixmaps/flags25x15/se.png and /dev/null differ diff --git a/pixmaps/flags25x15/sg.png b/pixmaps/flags25x15/sg.png deleted file mode 100644 index 51647797f..000000000 Binary files a/pixmaps/flags25x15/sg.png and /dev/null differ diff --git a/pixmaps/flags25x15/sh.png b/pixmaps/flags25x15/sh.png deleted file mode 100644 index 243cae2da..000000000 Binary files a/pixmaps/flags25x15/sh.png and /dev/null differ diff --git a/pixmaps/flags25x15/si.png b/pixmaps/flags25x15/si.png deleted file mode 100644 index 5c8e9a992..000000000 Binary files a/pixmaps/flags25x15/si.png and /dev/null differ diff --git a/pixmaps/flags25x15/sj.png b/pixmaps/flags25x15/sj.png deleted file mode 100644 index 3f24fb54b..000000000 Binary files a/pixmaps/flags25x15/sj.png and /dev/null differ diff --git a/pixmaps/flags25x15/sk.png b/pixmaps/flags25x15/sk.png deleted file mode 100644 index ee88a0736..000000000 Binary files a/pixmaps/flags25x15/sk.png and /dev/null differ diff --git a/pixmaps/flags25x15/sl.png b/pixmaps/flags25x15/sl.png deleted file mode 100644 index 608e0fe0d..000000000 Binary files a/pixmaps/flags25x15/sl.png and /dev/null differ diff --git a/pixmaps/flags25x15/sm.png b/pixmaps/flags25x15/sm.png deleted file mode 100644 index e38069d9b..000000000 Binary files a/pixmaps/flags25x15/sm.png and /dev/null differ diff --git a/pixmaps/flags25x15/sn.png b/pixmaps/flags25x15/sn.png deleted file mode 100644 index 4b99a6657..000000000 Binary files a/pixmaps/flags25x15/sn.png and /dev/null differ diff --git a/pixmaps/flags25x15/so.png b/pixmaps/flags25x15/so.png deleted file mode 100644 index 53db90314..000000000 Binary files a/pixmaps/flags25x15/so.png and /dev/null differ diff --git a/pixmaps/flags25x15/sr.png b/pixmaps/flags25x15/sr.png deleted file mode 100644 index 8643fae87..000000000 Binary files a/pixmaps/flags25x15/sr.png and /dev/null differ diff --git a/pixmaps/flags25x15/st.png b/pixmaps/flags25x15/st.png deleted file mode 100644 index 27041497a..000000000 Binary files a/pixmaps/flags25x15/st.png and /dev/null differ diff --git a/pixmaps/flags25x15/sv.png b/pixmaps/flags25x15/sv.png deleted file mode 100644 index f27b9be69..000000000 Binary files a/pixmaps/flags25x15/sv.png and /dev/null differ diff --git a/pixmaps/flags25x15/sy.png b/pixmaps/flags25x15/sy.png deleted file mode 100644 index 8816583f1..000000000 Binary files a/pixmaps/flags25x15/sy.png and /dev/null differ diff --git a/pixmaps/flags25x15/sz.png b/pixmaps/flags25x15/sz.png deleted file mode 100644 index fc4bb0232..000000000 Binary files a/pixmaps/flags25x15/sz.png and /dev/null differ diff --git a/pixmaps/flags25x15/tc.png b/pixmaps/flags25x15/tc.png deleted file mode 100644 index 162ed8ab1..000000000 Binary files a/pixmaps/flags25x15/tc.png and /dev/null differ diff --git a/pixmaps/flags25x15/td.png b/pixmaps/flags25x15/td.png deleted file mode 100644 index 3801b2f1f..000000000 Binary files a/pixmaps/flags25x15/td.png and /dev/null differ diff --git a/pixmaps/flags25x15/tf.png b/pixmaps/flags25x15/tf.png deleted file mode 100644 index c1a539549..000000000 Binary files a/pixmaps/flags25x15/tf.png and /dev/null differ diff --git a/pixmaps/flags25x15/tg.png b/pixmaps/flags25x15/tg.png deleted file mode 100644 index 2f80fe077..000000000 Binary files a/pixmaps/flags25x15/tg.png and /dev/null differ diff --git a/pixmaps/flags25x15/th.png b/pixmaps/flags25x15/th.png deleted file mode 100644 index bbe147583..000000000 Binary files a/pixmaps/flags25x15/th.png and /dev/null differ diff --git a/pixmaps/flags25x15/tj.png b/pixmaps/flags25x15/tj.png deleted file mode 100644 index 1f1b0dae4..000000000 Binary files a/pixmaps/flags25x15/tj.png and /dev/null differ diff --git a/pixmaps/flags25x15/tk.png b/pixmaps/flags25x15/tk.png deleted file mode 100644 index 5bcbefd91..000000000 Binary files a/pixmaps/flags25x15/tk.png and /dev/null differ diff --git a/pixmaps/flags25x15/tl.png b/pixmaps/flags25x15/tl.png deleted file mode 100644 index 1babb2b83..000000000 Binary files a/pixmaps/flags25x15/tl.png and /dev/null differ diff --git a/pixmaps/flags25x15/tm.png b/pixmaps/flags25x15/tm.png deleted file mode 100644 index 5b75e7ad0..000000000 Binary files a/pixmaps/flags25x15/tm.png and /dev/null differ diff --git a/pixmaps/flags25x15/tn.png b/pixmaps/flags25x15/tn.png deleted file mode 100644 index 9d7f7e32f..000000000 Binary files a/pixmaps/flags25x15/tn.png and /dev/null differ diff --git a/pixmaps/flags25x15/to.png b/pixmaps/flags25x15/to.png deleted file mode 100644 index bc2d04373..000000000 Binary files a/pixmaps/flags25x15/to.png and /dev/null differ diff --git a/pixmaps/flags25x15/tp.png b/pixmaps/flags25x15/tp.png deleted file mode 100644 index 1babb2b83..000000000 Binary files a/pixmaps/flags25x15/tp.png and /dev/null differ diff --git a/pixmaps/flags25x15/tr.png b/pixmaps/flags25x15/tr.png deleted file mode 100644 index a7d155845..000000000 Binary files a/pixmaps/flags25x15/tr.png and /dev/null differ diff --git a/pixmaps/flags25x15/tt.png b/pixmaps/flags25x15/tt.png deleted file mode 100644 index 4d18c0371..000000000 Binary files a/pixmaps/flags25x15/tt.png and /dev/null differ diff --git a/pixmaps/flags25x15/tv.png b/pixmaps/flags25x15/tv.png deleted file mode 100644 index d423b048e..000000000 Binary files a/pixmaps/flags25x15/tv.png and /dev/null differ diff --git a/pixmaps/flags25x15/tw.png b/pixmaps/flags25x15/tw.png deleted file mode 100644 index f233d0a89..000000000 Binary files a/pixmaps/flags25x15/tw.png and /dev/null differ diff --git a/pixmaps/flags25x15/tz.png b/pixmaps/flags25x15/tz.png deleted file mode 100644 index 8816583f1..000000000 Binary files a/pixmaps/flags25x15/tz.png and /dev/null differ diff --git a/pixmaps/flags25x15/ua.png b/pixmaps/flags25x15/ua.png deleted file mode 100644 index 1ff1a18b5..000000000 Binary files a/pixmaps/flags25x15/ua.png and /dev/null differ diff --git a/pixmaps/flags25x15/ug.png b/pixmaps/flags25x15/ug.png deleted file mode 100644 index 69c83f81d..000000000 Binary files a/pixmaps/flags25x15/ug.png and /dev/null differ diff --git a/pixmaps/flags25x15/um.png b/pixmaps/flags25x15/um.png deleted file mode 100644 index ac54a983f..000000000 Binary files a/pixmaps/flags25x15/um.png and /dev/null differ diff --git a/pixmaps/flags25x15/us.png b/pixmaps/flags25x15/us.png deleted file mode 100644 index ac54a983f..000000000 Binary files a/pixmaps/flags25x15/us.png and /dev/null differ diff --git a/pixmaps/flags25x15/uy.png b/pixmaps/flags25x15/uy.png deleted file mode 100644 index 7e58ac4e2..000000000 Binary files a/pixmaps/flags25x15/uy.png and /dev/null differ diff --git a/pixmaps/flags25x15/uz.png b/pixmaps/flags25x15/uz.png deleted file mode 100644 index 76707c52a..000000000 Binary files a/pixmaps/flags25x15/uz.png and /dev/null differ diff --git a/pixmaps/flags25x15/va.png b/pixmaps/flags25x15/va.png deleted file mode 100644 index 29692363a..000000000 Binary files a/pixmaps/flags25x15/va.png and /dev/null differ diff --git a/pixmaps/flags25x15/vc.png b/pixmaps/flags25x15/vc.png deleted file mode 100644 index 93164d109..000000000 Binary files a/pixmaps/flags25x15/vc.png and /dev/null differ diff --git a/pixmaps/flags25x15/ve.png b/pixmaps/flags25x15/ve.png deleted file mode 100644 index 92844bbec..000000000 Binary files a/pixmaps/flags25x15/ve.png and /dev/null differ diff --git a/pixmaps/flags25x15/vg.png b/pixmaps/flags25x15/vg.png deleted file mode 100644 index 8d226efe5..000000000 Binary files a/pixmaps/flags25x15/vg.png and /dev/null differ diff --git a/pixmaps/flags25x15/vi.png b/pixmaps/flags25x15/vi.png deleted file mode 100644 index 7916f3aaa..000000000 Binary files a/pixmaps/flags25x15/vi.png and /dev/null differ diff --git a/pixmaps/flags25x15/vn.png b/pixmaps/flags25x15/vn.png deleted file mode 100644 index 538b0810d..000000000 Binary files a/pixmaps/flags25x15/vn.png and /dev/null differ diff --git a/pixmaps/flags25x15/vu.png b/pixmaps/flags25x15/vu.png deleted file mode 100644 index e514f7b52..000000000 Binary files a/pixmaps/flags25x15/vu.png and /dev/null differ diff --git a/pixmaps/flags25x15/wf.png b/pixmaps/flags25x15/wf.png deleted file mode 100644 index c1a539549..000000000 Binary files a/pixmaps/flags25x15/wf.png and /dev/null differ diff --git a/pixmaps/flags25x15/ws.png b/pixmaps/flags25x15/ws.png deleted file mode 100644 index 8a26405b7..000000000 Binary files a/pixmaps/flags25x15/ws.png and /dev/null differ diff --git a/pixmaps/flags25x15/ye.png b/pixmaps/flags25x15/ye.png deleted file mode 100644 index 5b4520ff1..000000000 Binary files a/pixmaps/flags25x15/ye.png and /dev/null differ diff --git a/pixmaps/flags25x15/yt.png b/pixmaps/flags25x15/yt.png deleted file mode 100644 index c1a539549..000000000 Binary files a/pixmaps/flags25x15/yt.png and /dev/null differ diff --git a/pixmaps/flags25x15/yu.png b/pixmaps/flags25x15/yu.png deleted file mode 100644 index 7a89a78c1..000000000 Binary files a/pixmaps/flags25x15/yu.png and /dev/null differ diff --git a/pixmaps/flags25x15/za.png b/pixmaps/flags25x15/za.png deleted file mode 100644 index 38a122ce0..000000000 Binary files a/pixmaps/flags25x15/za.png and /dev/null differ diff --git a/pixmaps/flags25x15/zm.png b/pixmaps/flags25x15/zm.png deleted file mode 100644 index 7503819b9..000000000 Binary files a/pixmaps/flags25x15/zm.png and /dev/null differ diff --git a/pixmaps/flags25x15/zw.png b/pixmaps/flags25x15/zw.png deleted file mode 100644 index 0ccea687d..000000000 Binary files a/pixmaps/flags25x15/zw.png and /dev/null differ diff --git a/pixmaps/logo.ico b/pixmaps/logo.ico deleted file mode 100644 index ef5c3dd34..000000000 Binary files a/pixmaps/logo.ico and /dev/null differ diff --git a/plugins/BlocklistImport/__init__.py b/plugins/BlocklistImport/__init__.py deleted file mode 100644 index e11124364..000000000 --- a/plugins/BlocklistImport/__init__.py +++ /dev/null @@ -1,191 +0,0 @@ -## -# Copyright 2007 Steve 'Tarka' Smith (tarka@internode.on.net) -# Distributed under the same terms as Deluge -## - -plugin_name = "Blocklist Importer" -plugin_author = "Steve 'Tarka' Smith, updated by Mark Stahler" -plugin_version = "0.45" -plugin_description = _(""" -Download and import various IP blocklists. - -Currently this plugin can handle PeerGuardian (binary and text), -SafePeer and Emule lists. PeerGuardian 7zip format files are not -supported. Files may be specified as URLs or locations on the local -filesystem. - -A page with pointer to blocklist download sites is available on the -wiki: - -http://dev.deluge-torrent.org/wiki/BlocklistPlugin -""") - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return BlocklistImport(path, core, interface) - -#################### The plugin itself #################### - -import urllib, deluge.common, deluge.pref -from peerguardian import PGReader, PGException -from text import TextReader, GZMuleReader, PGZip -from ui import GTKConfig, GTKProgress -import os.path, os, time - -# List of formats supported. This is used to generate the UI list and -# specify the reader class. The last entry is for storage by the UI. -readers = {'p2bgz':[_("PeerGuardian P2B (GZip)"), PGReader, None], - 'pgtext':[_("PeerGuardian Text (Uncompressed)"), TextReader, None], - 'gzmule':[_("Emule IP list (GZip)"), GZMuleReader, None], - 'spzip':[_("SafePeer Text (Zipped)"), PGZip, None]} - -class BlocklistImport: - - def __init__(self, path, core, interface): - print "Found blocklist plugin ..." - # Save the path, interface, and core so they can be used later - self.path = path - self.core = core - self.interface = interface - self.cancelled = False - self.gtkconf = GTKConfig(self) - self.gtkprog = GTKProgress(self) - self.nimported = 0 - - self.blockfile = os.path.join(deluge.common.CONFIG_DIR, "blocklist.cache") - - conffile = os.path.join(deluge.common.CONFIG_DIR, "blocklist.conf") - self.config = deluge.pref.Preferences(filename=conffile, - global_defaults=False) - self.config.load() - - try: - load_after_days = self.config.get("load_after_days") - except: - self.config.set("load_after_days", -1) - - if self.config.has_key('url'): - self.loadlist(fetch=self.config.get('load_after_days')) - - - def _download_update(self, curr, chunksize, size): - incs = float(size) / float(chunksize) - self.gtkprog.download_prog(curr/incs) - - def loadlist(self, fetch=-1): - # Stop all torrents - self.paused_or_not = {} - for unique_ID in self.core.unique_IDs: - self.paused_or_not[unique_ID] = self.core.is_user_paused(unique_ID) - if not self.paused_or_not[unique_ID]: - self.core.set_user_pause(unique_ID, True, enforce_queue=False) - - self.gtkprog.start() - - # Compare modified time with load_after_days - try: - liststats = os.stat(self.blockfile) - list_timestamp = liststats.st_mtime - now_timestamp = time.time() - days_update = self.config.get('load_after_days') - if days_update == None: - days_update = 0 - - # Seconds in a day = 86400 - # Check to see if todays timestamp is older than the list plus days in config - - if now_timestamp >= (list_timestamp + (86400 * days_update)): - fetch = -1 - print 'New Blocklist required...' - - # If blocklist doesnt exist - except OSError, e: - pass - - # Attempt initial import - if fetch == -1: - print "Fetching",self.config.get('url') - self.gtkprog.start_download() - try: - filename, headers = urllib.urlretrieve(self.config.get('url'), - filename=self.blockfile, - reporthook=self._download_update) - except IOError, e: - err = ui.GTKError(_("Couldn't download URL") + ": %s"%e) - self.gtkprog.stop() - return - - self.gtkprog.start_import() - - self.core.reset_ip_filter() - ltype = self.config.get('listtype') - print "importing with",ltype - - try: - reader = readers[ltype][1](self.blockfile) - except IOError, e: - err = ui.GTKError(_("Couldn't open blocklist file") + ": %s"%e) - self.gtkprog.stop() - return - - print "Starting import" - try: - ips = reader.next() - except: - ui.GTKError(_("Wrong file type or corrupted blocklist file.")) - curr = 0 - try: - while ips and not self.cancelled: - self.core.add_range_to_ip_filter(*ips) - ips = reader.next() - curr += 1 - if curr % 100 == 0: - self.gtkprog.import_prog(text=(_("Imported") + " %s " + _("IPs"))%curr) - else: - self.gtkprog.import_prog() - - except: - self.gtkprog.stop() - reader.close() - return - - self.core.set_ip_filter() - reader.close() - self.nimported = curr - self.gtkprog.end_import() - print "Import finished" - - self.gtkprog.stop() - self.cancelled = False - #restart torrents that werent paused by us - for unique_ID in self.core.unique_IDs: - if not self.paused_or_not[unique_ID]: - self.core.set_user_pause(unique_ID, False, enforce_queue=False) - - def configure(self, window): - self.gtkconf.start(self.config.get('listtype'), - self.config.get('url'), - self.config.get('load_after_days'), - window) - - def setconfig(self, url, load_after_days, listtype): - self.config.set('url', url) - self.config.set('load_after_days', load_after_days) - self.config.set('listtype', listtype) - self.config.save() - - self.loadlist() - - def disable(self): - self.core.reset_ip_filter() - - def unload(self): - self.core.reset_ip_filter() - - def update(self): - msg = ("[" + _("Blocklist") + ": %s " + _("entries") + "]") % self.nimported - self.interface.statusbar_temp_msg += ' ' + msg diff --git a/plugins/BlocklistImport/listfile1.txt b/plugins/BlocklistImport/listfile1.txt deleted file mode 100644 index 62fa68b53..000000000 --- a/plugins/BlocklistImport/listfile1.txt +++ /dev/null @@ -1 +0,0 @@ -Bogon,:0.0.0.0-3.255.255.255 diff --git a/plugins/BlocklistImport/listfile2.txt b/plugins/BlocklistImport/listfile2.txt deleted file mode 100644 index 0875e7b77..000000000 --- a/plugins/BlocklistImport/listfile2.txt +++ /dev/null @@ -1 +0,0 @@ -Bogon,:1.1.1.1-3.255.255.255 diff --git a/plugins/BlocklistImport/nipfilter.dat.gz b/plugins/BlocklistImport/nipfilter.dat.gz deleted file mode 100644 index dcda95298..000000000 Binary files a/plugins/BlocklistImport/nipfilter.dat.gz and /dev/null differ diff --git a/plugins/BlocklistImport/pg.txt b/plugins/BlocklistImport/pg.txt deleted file mode 100644 index edd08e850..000000000 --- a/plugins/BlocklistImport/pg.txt +++ /dev/null @@ -1,4 +0,0 @@ -General Electric Company:3.0.0.0-3.255.255.255 - -s0-0.ciscoseattle.bbnplanet.net:4.0.25.146-4.0.25.148 - diff --git a/plugins/BlocklistImport/splist.txt b/plugins/BlocklistImport/splist.txt deleted file mode 100644 index 6b6ecc2af..000000000 --- a/plugins/BlocklistImport/splist.txt +++ /dev/null @@ -1,2 +0,0 @@ -Bogon,:0.0.0.0-3.255.255.255 -s0-0.c:4.0.25.146-4.0.25.148 diff --git a/plugins/BlocklistImport/test.py b/plugins/BlocklistImport/test.py deleted file mode 100644 index 1d03ee2cf..000000000 --- a/plugins/BlocklistImport/test.py +++ /dev/null @@ -1,39 +0,0 @@ -## -# Copyright 2007 Steve 'Tarka' Smith (tarka@internode.on.net) -# Distributed under the same terms as Deluge -## - -import unittest -from text import TextReader, GZMuleReader, PGZip - - -class ImportTests(unittest.TestCase): - - def testpgtext(self): - fr = TextReader("pg.txt") - ips = fr.next() - self.assertEqual("3.0.0.0", ips[0]) - self.assertEqual("3.255.255.255", ips[1]) - - def testMule(self): - fr = GZMuleReader("nipfilter.dat.gz") - ips = fr.next() - self.assertEqual("0.0.0.0", ips[0]) - self.assertEqual("3.255.255.255", ips[1]) - - def testZip(self): - fr = PGZip("splist.zip") - ips = fr.next() - print "wibble wibble",ips - self.assertEqual("1.1.1.1", ips[0]) - self.assertEqual("3.255.255.255", ips[1]) - - ips = fr.next() - self.assertEqual("0.0.0.0", ips[0]) - self.assertEqual("3.255.255.255", ips[1]) - - ips = fr.next() - self.assertEqual(ips, False) - -if __name__ == '__main__': - unittest.main() diff --git a/plugins/BlocklistImport/ui.py b/plugins/BlocklistImport/ui.py deleted file mode 100644 index e7bcb5a24..000000000 --- a/plugins/BlocklistImport/ui.py +++ /dev/null @@ -1,212 +0,0 @@ -## -# Copyright 2007 Steve 'Tarka' Smith (tarka@internode.on.net) -# Distributed under the same terms as Deluge -## - -import gobject, gtk -import BlocklistImport - -class GTKConfig(gtk.Dialog): - def __init__(self, plugin): - gtk.Dialog.__init__(self, title="Blocklist Config", - parent=None, - buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, - gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) - self.set_property("skip-taskbar-hint", True) - self.set_property("skip-pager-hint", True) - - self.plugin = plugin - # Setup - self.set_border_width(12) - self.vbox.set_spacing(6) - - # List source - label = gtk.Label() - label.set_markup('' + _("Blocklist URL") + '') - self.url = gtk.Entry() - - ls = gtk.ListStore(gobject.TYPE_STRING, # Long name - gobject.TYPE_STRING) # Short name - for k in BlocklistImport.readers.keys(): - i = ls.append([BlocklistImport.readers[k][0], k]) - BlocklistImport.readers[k][2] = ls.get_path(i) - - cell = gtk.CellRendererText() - cell.set_property('xpad', 5) # padding for status text - - self.listtype = gtk.ComboBox(model=ls) - self.listtype.pack_start(cell, False) - self.listtype.add_attribute(cell, 'text', 0) - self.listtype.set_active(0) - - hbox = gtk.HBox(False, 6) - hbox.pack_start(label) - hbox.pack_end(self.url, expand=True, fill=True) - - self.vbox.pack_start(self.listtype) - self.vbox.pack_start(hbox) - - # Load on start - # gtk.SpinButton(adjustment=None, climb_rate=0.0, digits=0) - label2 = gtk.Label() - label2.set_markup('' + _("Download new blocklist every") + '') - - self.load_after_days = gtk.SpinButton(None, 1.0, 0) - self.load_after_days.set_increments(1, 3) - self.load_after_days.set_range(-1, 14) - - label3 = gtk.Label() - label3.set_markup('' + _("days") + '') - - hbox2 = gtk.HBox(False, 6) - hbox2.pack_start(label2) - hbox2.pack_start(self.load_after_days) - hbox2.pack_start(label3) - - self.vbox.pack_start(hbox2) - - self.connect('response', self.ok) - self.connect('close', self.cancel) - self.connect("delete_event", self.cancel) - - self.hide_all() - - - def ok(self, dialog, response): - self.hide_all() - - if response != gtk.RESPONSE_ACCEPT: - self.cancel(dialog) - return - - ls = self.listtype.get_model() - ltype = ls[self.listtype.get_active()][1] - url = self.url.get_text() - days = self.load_after_days.get_value() - - self.plugin.setconfig(url, days, ltype) - - - def cancel(self, dialog, signal=None): - self.hide_all() - if signal: - return True - - def start(self, ltype, url, days, window): - self.set_transient_for(window) - if ltype: - path = BlocklistImport.readers[ltype][2] - i = self.listtype.get_model().get_iter(path) - self.listtype.set_active_iter(i) - - if url: - self.url.set_text(url) - - if days: - self.load_after_days.set_value(days) - - self.show_all() - - -class GTKProgress(gtk.Dialog): - def __init__(self, plugin): - gtk.Dialog.__init__(self, title="Loading Blocklist", - parent=None, - buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) - self.plugin = plugin - - # Setup - self.set_border_width(12) - self.vbox.set_spacing(6) - - label = gtk.Label() - label.set_markup('' + _("Loading and installing blocklist") + '') - self.vbox.pack_start(label) - - self.progress = gtk.ProgressBar() - self.vbox.pack_start(self.progress) - - self.connect('response', self.response) - self.connect('close', self.cancel) - self.connect("delete_event", self.cancel) - - self.hide_all() - - def start_download(self): - self.progress.set_text(_("Downloading")) - self.progress.set_fraction(0.0) - self.update() - - def download_prog(self, fract): - if fract > 1.0: - fract = 1.0 - self.progress.set_fraction(fract) - self.update() - - def start_import(self): - self.progress.set_text(_("Importing")) - self.progress.set_fraction(0.0) - self.progress.set_pulse_step(0.0075) - self.update() - - def import_prog(self, text=None): - if text: - self.progress.set_text(text) - self.update() - - def end_import(self): - self.progress.set_text(_("Complete")) - self.progress.set_fraction(1.0) - self.update() - - - def response(self, dialog, response): - self.cancel(dialog) - - def cancel(self, dialog, signal=None): - print "Cancelling" - self.plugin.cancelled = True - self.hide_all() - if signal: - return True - - def start(self): - self.show_all() - self.update() - - def stop(self): - self.hide_all() - - def update(self): - while gtk.events_pending(): - not gtk.main_iteration(block=True) - - -class GTKError(gtk.Dialog): - def __init__(self, message): - gtk.Dialog.__init__(self, title="Error", - parent=None, - buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) - - # Setup - self.set_border_width(12) - self.vbox.set_spacing(6) - - # List source - label = gtk.Label() - label.set_text(message) - self.vbox.pack_start(label) - - self.connect('response', self.ok) - self.connect('close', self.cancel) - self.connect("delete_event", self.cancel) - - self.show_all() - - def ok(self, dialog, response): - self.hide_all() - - def cancel(self, dialog, signal): - self.hide_all() - if signal: - return True diff --git a/plugins/DesiredRatio/__init__.py b/plugins/DesiredRatio/__init__.py deleted file mode 100644 index b312d8a37..000000000 --- a/plugins/DesiredRatio/__init__.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright (C) 2007 - Andrew Resch -# -# 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 2, 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 St, Fifth Floor, Boston, MA 02110-1301 USA. - -### Initialization ### - -plugin_name = "Desired Ratio" -plugin_author = "Andrew Resch" -plugin_version = "0.1" -plugin_description = _("Set the desired ratio for a torrent.") - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return DesiredRatio(path, core, interface) - -### The Plugin ### - -DEFAULT_PREFS = { - "ratios": [1.0, 1.5, 2.0, 2.5, 3.0] -} - -import deluge -import gtk, gtk.glade -import os.path - -class DesiredRatio: - - def __init__(self, path, core, interface): - print "Found DesiredRatio plugin..." - self.path = path - self.core = core - self.interface = interface - self.set_ratios = {} - self.callback_ids = [] - - # Setup preferences - self.config = deluge.pref.Preferences(filename=os.path.join(deluge.common.CONFIG_DIR, "desired_ratio.conf"), global_defaults=False, defaults=DEFAULT_PREFS) - - # Connect to events for the torrent menu so we know when to build and remove our sub-menu - self.callback_ids.append(self.interface.torrent_menu.connect_after("realize", self.torrent_menu_show)) - self.callback_ids.append(self.interface.torrent_menu.connect("show", self.torrent_menu_show)) - self.callback_ids.append(self.interface.torrent_menu.connect("hide", self.torrent_menu_hide)) - for torrent in self.core.get_queue(): - unique_ID = self.core.get_torrent_unique_id(torrent) - try: - if self.core.unique_IDs[unique_ID].desired_ratio != 1.0: - value = float(self.core.unique_IDs[unique_ID].desired_ratio) - self.core.set_ratio(unique_ID, value) - self.set_ratios[unique_ID] = value - if value not in self.config.get("ratios") and value >= 1: - self.config.get("ratios").insert(0, value) - self.config.get("ratios").pop() - except AttributeError: - pass - - def torrent_menu_show(self, widget, data=None): - # Get the selected torrent - self.unique_ID = self.interface.get_selected_torrent() - - # Make the sub-menu for the torrent menu - self.ratio_menuitem = gtk.MenuItem(_("_Desired Ratio")) - - - - self.ratio_menu = self.interface.build_menu_radio_list(self.config.get("ratios"), self.ratio_clicked, self.get_torrent_desired_ratio(), None, True, _("_Not Set"), 1, None) - - self.ratio_menuitem.set_submenu(self.ratio_menu) - self.interface.torrent_menu.append(self.ratio_menuitem) - - self.ratio_menuitem.show_all() - - def torrent_menu_hide(self, widget): - try: - self.interface.torrent_menu.remove(self.ratio_menuitem) - except AttributeError: - pass - - def update(self): - pass - - def unload(self): - # Disconnect all callbacks - for callback_id in self.callback_ids: - self.interface.torrent_menu.disconnect(callback_id) - - self.callback_ids = [] - - # Reset all desired ratios in the core - for unique_ID, ratio in self.set_ratios.items(): - if ratio >= 1: - self.core.set_ratio(unique_ID, ratio) - - self.set_ratios = {} - - def ratio_clicked(self, widget): - value = widget.get_children()[0].get_text() - if value == _("Not Set"): - value = 0.0 - - if value == _("Other..."): - dialog_glade = gtk.glade.XML(deluge.common.get_glade_file("dgtkpopups.glade")) - speed_dialog = dialog_glade.get_widget("speed_dialog") - spin_title = dialog_glade.get_widget("spin_title") - spin_title.set_text(_("Desired Ratio")) - spin_speed = dialog_glade.get_widget("spin_speed") - spin_speed.set_value(self.get_torrent_desired_ratio()) - spin_speed.set_increments(0.1, 1.0) - spin_speed.set_digits(1) - spin_speed.set_range(1.0, 1000.0) - spin_speed.select_region(0, -1) - response = speed_dialog.run() - if response == 1: # OK Response - value = spin_speed.get_value() - else: - speed_dialog.destroy() - return - speed_dialog.destroy() - - value = float(value) # Make sure the value is a float - - # Set the ratio in the core and remember the setting - self.core.set_ratio(self.unique_ID, value) - self.set_ratios[self.unique_ID] = value - self.core.unique_IDs[self.unique_ID].desired_ratio = value - - # Update the ratios list if necessary - if value not in self.config.get("ratios") and value >= 1: - self.config.get("ratios").insert(0, value) - self.config.get("ratios").pop() - - def get_torrent_desired_ratio(self): - return self.set_ratios.get(self.unique_ID, 1) - diff --git a/plugins/EventLogging/__init__.py b/plugins/EventLogging/__init__.py deleted file mode 100644 index 2a0f22950..000000000 --- a/plugins/EventLogging/__init__.py +++ /dev/null @@ -1,304 +0,0 @@ -# Copyright (C) 2007 - Micah Bucy -# -# 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 2, 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 St, Fifth Floor, Boston, MA 02110-1301 USA. - -### Initialization ### - -plugin_name = "Event Logging" -plugin_author = "Micah Bucy" -plugin_version = "0.2" -plugin_description = _(""" -Adds a tab with log of selected events. - -Event messages come from libtorrent alerts. -If you want those strings translated to your locale, -you'll have to report the issue with libtorrent, not deluge. - -Regarding the log files, the logs are saved in a log -directory within the deluge config directory. Event -messages for specific torrents are saved to individual -log files named the same as the associated .torrent -file. Event messages not specific to any torrent are -saved to logs named after the events -(eg peer_messages.log). -Event messages in the log files also include a timestamp. -The user is responsible to cleanout the logs. - -As of v0.2 -Events are now truncated in display. Log files are not. -New events are now displayed at the top. -""") - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return EventLogging(path, core, interface) - -### The Plugin ### -import deluge -import gtk -import os.path -from EventLogging.tab_log import LogTabManager - -class EventLogging: - - def __init__(self, path, core, interface): - print "Found LogEvents plugin..." - self.manager = core - self.parent = interface - # Create an options file and try to load existing Values - self.config_file = os.path.join(deluge.common.CONFIG_DIR, "event_logging.conf") - self.config = deluge.pref.Preferences(self.config_file, False) - try: - self.config.load() - except IOError: - # File does not exist - pass - self.dialog_initialize = True - self.glade = gtk.glade.XML(os.path.join(path, "event_logging_preferences.glade")) - self.dialog = self.glade.get_widget("dialog") - self.dialog.set_position(gtk.WIN_POS_CENTER) - self.glade.signal_autoconnect({ - 'on_button_cancel_clicked': self.cancel_clicked, - 'on_button_ok_clicked': self.ok_clicked - }) - self.viewport = gtk.Viewport() - self.scrolledWindow = gtk.ScrolledWindow() - self.scrolledWindow.add(self.viewport) - self.scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - - self.topWidget = self.scrolledWindow - - self.parentNotebook = self.parent.notebook - - self.parentNotebook.append_page(self.topWidget, gtk.Label(_("Event Log"))) - self.viewport.show() - self.scrolledWindow.show() - self.tab_log = LogTabManager(self.viewport, self.manager) - self.tab_log.build_log_view() - if self.config.get("enable_finished"): - self.manager.connect_event(self.manager.constants['EVENT_FINISHED'], self.tab_log.handle_event) - if self.config.get("enable_peer_error"): - self.manager.connect_event(self.manager.constants['EVENT_PEER_ERROR'], self.tab_log.handle_event) - if self.config.get("enable_invalid_request"): - self.manager.connect_event(self.manager.constants['EVENT_INVALID_REQUEST'], self.tab_log.handle_event) - if self.config.get("enable_file_error"): - self.manager.connect_event(self.manager.constants['EVENT_FILE_ERROR'], self.tab_log.handle_event) - if self.config.get("enable_hash_failed_error"): - self.manager.connect_event(self.manager.constants['EVENT_HASH_FAILED_ERROR'], self.tab_log.handle_event) - if self.config.get("enable_peer_ban_error"): - self.manager.connect_event(self.manager.constants['EVENT_PEER_BAN_ERROR'], self.tab_log.handle_event) - if self.config.get("enable_fastresume_rejected_error"): - self.manager.connect_event(self.manager.constants['EVENT_FASTRESUME_REJECTED_ERROR'], self.tab_log.handle_event) - if self.config.get("enable_tracker_announce"): - self.manager.connect_event(self.manager.constants['EVENT_TRACKER_ANNOUNCE'], self.tab_log.handle_event) - if self.config.get("enable_tracker_reply"): - self.manager.connect_event(self.manager.constants['EVENT_TRACKER_REPLY'], self.tab_log.handle_event) - if self.config.get("enable_tracker_alert"): - self.manager.connect_event(self.manager.constants['EVENT_TRACKER_ALERT'], self.tab_log.handle_event) - if self.config.get("enable_tracker_warning"): - self.manager.connect_event(self.manager.constants['EVENT_TRACKER_WARNING'], self.tab_log.handle_event) - if self.config.get("enable_storage_moved"): - self.manager.connect_event(self.manager.constants['EVENT_STORAGE_MOVED'], self.tab_log.handle_event) - if self.config.get("enable_piece_finished"): - self.manager.connect_event(self.manager.constants['EVENT_PIECE_FINISHED'], self.tab_log.handle_event) - if self.config.get("enable_block_downloading"): - self.manager.connect_event(self.manager.constants['EVENT_BLOCK_DOWNLOADING'], self.tab_log.handle_event) - if self.config.get("enable_block_finished"): - self.manager.connect_event(self.manager.constants['EVENT_BLOCK_FINISHED'], self.tab_log.handle_event) - if self.config.get("enable_peer_blocked"): - self.manager.connect_event(self.manager.constants['EVENT_PEER_BLOCKED'], self.tab_log.handle_event) - if self.config.get("enable_other"): - self.manager.connect_event(self.manager.constants['EVENT_OTHER'], self.tab_log.handle_event) - if self.config.get("enable_log_files"): - self.tab_log.enable_log_files() - - def unload(self): - if self.config.get("enable_finished"): - self.manager.disconnect_event(self.manager.constants['EVENT_FINISHED'], self.tab_log.handle_event) - if self.config.get("enable_peer_error"): - self.manager.disconnect_event(self.manager.constants['EVENT_PEER_ERROR'], self.tab_log.handle_event) - if self.config.get("enable_invalid_request"): - self.manager.disconnect_event(self.manager.constants['EVENT_INVALID_REQUEST'], self.tab_log.handle_event) - if self.config.get("enable_file_error"): - self.manager.disconnect_event(self.manager.constants['EVENT_FILE_ERROR'], self.tab_log.handle_event) - if self.config.get("enable_hash_failed_error"): - self.manager.disconnect_event(self.manager.constants['EVENT_HASH_FAILED_ERROR'], self.tab_log.handle_event) - if self.config.get("enable_peer_ban_error"): - self.manager.disconnect_event(self.manager.constants['EVENT_PEER_BAN_ERROR'], self.tab_log.handle_event) - if self.config.get("enable_fastresume_rejected_error"): - self.manager.disconnect_event(self.manager.constants['EVENT_FASTRESUME_REJECTED_ERROR'], self.tab_log.handle_event) - if self.config.get("enable_tracker_announce"): - self.manager.disconnect_event(self.manager.constants['EVENT_TRACKER_ANNOUNCE'], self.tab_log.handle_event) - if self.config.get("enable_tracker_reply"): - self.manager.disconnect_event(self.manager.constants['EVENT_TRACKER_REPLY'], self.tab_log.handle_event) - if self.config.get("enable_tracker_alert"): - self.manager.disconnect_event(self.manager.constants['EVENT_TRACKER_ALERT'], self.tab_log.handle_event) - if self.config.get("enable_tracker_warning"): - self.manager.disconnect_event(self.manager.constants['EVENT_TRACKER_WARNING'], self.tab_log.handle_event) - if self.config.get("enable_storage_moved"): - self.manager.disconnect_event(self.manager.constants['EVENT_STORAGE_MOVED'], self.tab_log.handle_event) - if self.config.get("enable_piece_finished"): - self.manager.disconnect_event(self.manager.constants['EVENT_PIECE_FINISHED'], self.tab_log.handle_event) - if self.config.get("enable_block_downloading"): - self.manager.disconnect_event(self.manager.constants['EVENT_BLOCK_DOWNLOADING'], self.tab_log.handle_event) - if self.config.get("enable_block_finished"): - self.manager.disconnect_event(self.manager.constants['EVENT_BLOCK_FINISHED'], self.tab_log.handle_event) - if self.config.get("enable_peer_blocked"): - self.manager.disconnect_event(self.manager.constants['EVENT_PEER_BLOCKED'], self.tab_log.handle_event) - if self.config.get("enable_other"): - self.manager.disconnect_event(self.manager.constants['EVENT_OTHER'], self.tab_log.handle_event) - self.tab_log.clear_log_store() - numPages = self.parentNotebook.get_n_pages() - for page in xrange(numPages): - if self.parentNotebook.get_nth_page(page) == self.topWidget: - self.parentNotebook.remove_page(page) - break - self.config.save(self.config_file) - - def update(self): - pass - - def configure(self, window): - self.dialog_initialize = True - try: - self.glade.get_widget("chk_finished").set_active(self.config.get("enable_finished")) - except: - self.glade.get_widget("chk_finished").set_active(False) - try: - self.glade.get_widget("chk_peer_error").set_active(self.config.get("enable_peer_error")) - except: - self.glade.get_widget("chk_peer_error").set_active(False) - try: - self.glade.get_widget("chk_invalid_request").set_active(self.config.get("enable_invalid_request")) - except: - self.glade.get_widget("chk_invalid_request").set_active(False) - try: - self.glade.get_widget("chk_file_error").set_active(self.config.get("enable_file_error")) - except: - self.glade.get_widget("chk_file_error").set_active(False) - try: - self.glade.get_widget("chk_hash_failed_error").set_active(self.config.get("enable_hash_failed_error")) - except: - self.glade.get_widget("chk_hash_failed_error").set_active(False) - try: - self.glade.get_widget("chk_peer_ban_error").set_active(self.config.get("enable_peer_ban_error")) - except: - self.glade.get_widget("chk_peer_ban_error").set_active(False) - try: - self.glade.get_widget("chk_fastresume_rejected_error").set_active(self.config.get("enable_fastresume_rejected_error")) - except: - self.glade.get_widget("chk_fastresume_rejected_error").set_active(False) - try: - self.glade.get_widget("chk_tracker_announce").set_active(self.config.get("enable_tracker_announce")) - except: - self.glade.get_widget("chk_tracker_announce").set_active(False) - try: - self.glade.get_widget("chk_tracker_reply").set_active(self.config.get("enable_tracker_reply")) - except: - self.glade.get_widget("chk_tracker_reply").set_active(False) - try: - self.glade.get_widget("chk_tracker_alert").set_active(self.config.get("enable_tracker_alert")) - except: - self.glade.get_widget("chk_tracker_alert").set_active(False) - try: - self.glade.get_widget("chk_tracker_warning").set_active(self.config.get("enable_tracker_warning")) - except: - self.glade.get_widget("chk_tracker_warning").set_active(False) - try: - self.glade.get_widget("chk_storage_moved").set_active(self.config.get("enable_storage_moved")) - except: - self.glade.get_widget("chk_storage_moved").set_active(False) - try: - self.glade.get_widget("chk_piece_finished").set_active(self.config.get("enable_piece_finished")) - except: - self.glade.get_widget("chk_piece_finished").set_active(False) - try: - self.glade.get_widget("chk_block_downloading").set_active(self.config.get("enable_block_downloading")) - except: - self.glade.get_widget("chk_block_downloading").set_active(False) - try: - self.glade.get_widget("chk_block_finished").set_active(self.config.get("enable_block_finished")) - except: - self.glade.get_widget("chk_block_finished").set_active(False) - try: - self.glade.get_widget("chk_peer_blocked").set_active(self.config.get("enable_peer_blocked")) - except: - self.glade.get_widget("chk_peer_blocked").set_active(False) - try: - self.glade.get_widget("chk_other").set_active(self.config.get("enable_other")) - except: - self.glade.get_widget("chk_other").set_active(False) - try: - self.glade.get_widget("chk_log_files").set_active(self.config.get("enable_log_files")) - except: - self.glade.get_widget("chk_log_files").set_active(False) - self.dialog_initialize = False - self.dialog.set_transient_for(window) - self.dialog.show() - - def update_config(self, event_id, value): - if value: - self.manager.connect_event(event_id, self.tab_log.handle_event) - else: - self.manager.disconnect_event(event_id, self.tab_log.handle_event) - - def ok_clicked(self, src): - self.dialog.hide() - self.update_config(self.manager.constants['EVENT_FINISHED'], self.glade.get_widget("chk_finished").get_active()) - self.config.set("enable_finished", self.glade.get_widget("chk_finished").get_active()) - self.update_config(self.manager.constants['EVENT_PEER_ERROR'], self.glade.get_widget("chk_peer_error").get_active()) - self.config.set("enable_peer_error", self.glade.get_widget("chk_peer_error").get_active()) - self.update_config(self.manager.constants['EVENT_INVALID_REQUEST'], self.glade.get_widget("chk_invalid_request").get_active()) - self.config.set("enable_invalid_request", self.glade.get_widget("chk_invalid_request").get_active()) - self.update_config(self.manager.constants['EVENT_FILE_ERROR'], self.glade.get_widget("chk_file_error").get_active()) - self.config.set("enable_file_error", self.glade.get_widget("chk_file_error").get_active()) - self.update_config(self.manager.constants['EVENT_HASH_FAILED_ERROR'], self.glade.get_widget("chk_hash_failed_error").get_active()) - self.config.set("enable_hash_failed_error", self.glade.get_widget("chk_hash_failed_error").get_active()) - self.update_config(self.manager.constants['EVENT_PEER_BAN_ERROR'], self.glade.get_widget("chk_peer_ban_error").get_active()) - self.config.set("enable_peer_ban_error", self.glade.get_widget("chk_peer_ban_error").get_active()) - self.update_config(self.manager.constants['EVENT_FASTRESUME_REJECTED_ERROR'], self.glade.get_widget("chk_fastresume_rejected_error").get_active()) - self.config.set("enable_fastresume_rejected_error", self.glade.get_widget("chk_fastresume_rejected_error").get_active()) - self.update_config(self.manager.constants['EVENT_TRACKER_ANNOUNCE'], self.glade.get_widget("chk_tracker_announce").get_active()) - self.config.set("enable_tracker_announce", self.glade.get_widget("chk_tracker_announce").get_active()) - self.update_config(self.manager.constants['EVENT_TRACKER_REPLY'], self.glade.get_widget("chk_tracker_reply").get_active()) - self.config.set("enable_tracker_reply", self.glade.get_widget("chk_tracker_reply").get_active()) - self.update_config(self.manager.constants['EVENT_TRACKER_ALERT'], self.glade.get_widget("chk_tracker_alert").get_active()) - self.config.set("enable_tracker_alert", self.glade.get_widget("chk_tracker_alert").get_active()) - self.update_config(self.manager.constants['EVENT_TRACKER_WARNING'], self.glade.get_widget("chk_tracker_warning").get_active()) - self.config.set("enable_tracker_warning", self.glade.get_widget("chk_tracker_warning").get_active()) - self.update_config(self.manager.constants['EVENT_STORAGE_MOVED'], self.glade.get_widget("chk_storage_moved").get_active()) - self.config.set("enable_storage_moved", self.glade.get_widget("chk_storage_moved").get_active()) - self.update_config(self.manager.constants['EVENT_PIECE_FINISHED'], self.glade.get_widget("chk_piece_finished").get_active()) - self.config.set("enable_piece_finished", self.glade.get_widget("chk_piece_finished").get_active()) - self.update_config(self.manager.constants['EVENT_BLOCK_DOWNLOADING'], self.glade.get_widget("chk_block_downloading").get_active()) - self.config.set("enable_block_downloading", self.glade.get_widget("chk_block_downloading").get_active()) - self.update_config(self.manager.constants['EVENT_BLOCK_FINISHED'], self.glade.get_widget("chk_block_finished").get_active()) - self.config.set("enable_block_finished", self.glade.get_widget("chk_block_finished").get_active()) - self.update_config(self.manager.constants['EVENT_PEER_BLOCKED'], self.glade.get_widget("chk_peer_blocked").get_active()) - self.config.set("enable_peer_blocked", self.glade.get_widget("chk_peer_blocked").get_active()) - self.update_config(self.manager.constants['EVENT_OTHER'], self.glade.get_widget("chk_other").get_active()) - self.config.set("enable_other", self.glade.get_widget("chk_other").get_active()) - if self.glade.get_widget("chk_log_files").get_active(): - self.tab_log.enable_log_files() - else: - self.tab_log.disable_log_files() - self.config.set("enable_log_files", self.glade.get_widget("chk_log_files").get_active()) - - def cancel_clicked(self, src): - self.dialog.hide() diff --git a/plugins/EventLogging/event_logging_preferences.glade b/plugins/EventLogging/event_logging_preferences.glade deleted file mode 100644 index 1ac47c1b0..000000000 --- a/plugins/EventLogging/event_logging_preferences.glade +++ /dev/null @@ -1,334 +0,0 @@ - - - - - - 5 - Event Logging Preferences - 400 - 150 - GDK_WINDOW_TYPE_HINT_NORMAL - True - True - True - False - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - 2 - - - True - 20 - - - True - True - Enable log files - True - 0 - True - - - 19 - 20 - - - - - True - Log files - - - 18 - 19 - - - - - True - True - Other - True - 0 - True - - - 17 - 18 - - - - - True - True - Peer blocked - True - 0 - True - - - 16 - 17 - - - - - True - True - Block finished - True - 0 - True - - - 15 - 16 - - - - - True - True - Block downloading - True - 0 - True - - - 14 - 15 - - - - - True - True - Piece finished - True - 0 - True - - - 13 - 14 - - - - - True - True - Storage moved - True - 0 - True - - - 12 - 13 - - - - - True - True - Tracker warning - True - 0 - True - - - 11 - 12 - - - - - True - True - Tracker alert - True - 0 - True - - - 10 - 11 - - - - - True - True - Tracker reply - True - 0 - True - - - 9 - 10 - - - - - True - True - Tracker announce - True - 0 - True - - - 8 - 9 - - - - - True - True - Fastresume rejected error - True - 0 - True - - - 7 - 8 - - - - - True - True - Peer ban error - True - 0 - True - - - 6 - 7 - - - - - True - True - Hash failed error - True - 0 - True - - - 5 - 6 - - - - - True - True - File error - True - 0 - True - - - 4 - 5 - - - - - True - True - Invalid request - True - 0 - True - - - 3 - 4 - - - - - True - True - Peer messages - True - 0 - True - - - 2 - 3 - - - - - True - True - Torrent finished - True - 0 - True - - - 1 - 2 - - - - - True - Select events to log - - - - - False - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - GTK_BUTTONBOX_END - - - True - gtk-cancel - True - 0 - - - - - - True - gtk-ok - True - 1 - - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/plugins/EventLogging/tab_log.py b/plugins/EventLogging/tab_log.py deleted file mode 100644 index 68c51b442..000000000 --- a/plugins/EventLogging/tab_log.py +++ /dev/null @@ -1,246 +0,0 @@ -# -*- coding: utf-8 -*- -# -# tab_log.py -# -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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. - -import gtk -import os -import time - -from deluge import common - -class LogTabManager(object): - def __init__(self, viewport, manager): - self.log_files = False - self.viewport = viewport - self.vbox = None - self.manager = manager - self.logdir = os.path.join(common.CONFIG_DIR, 'logs') - if not os.path.isdir(self.logdir): - os.mkdir(self.logdir) - self.labels = [] - - def clear_log_store(self): - if not self.vbox is None: - self.vbox.destroy() - self.vbox = None - - def build_log_view(self): - self.vbox = gtk.VBox() - self.viewport.add(self.vbox) - self.vbox.show_all() - - def enable_log_files(self): - self.log_files = True - - def disable_log_files(self): - self.log_files = False - - def handle_event(self, event): - event_message = None - if event['event_type'] is self.manager.constants['EVENT_FINISHED']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - event_message = _("Torrent finished") + " {"+ _("event message: ") + event['message'] + ", "\ - + _("torrent: ") + torrent + "}" - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_PEER_ERROR']: - event_message = _("Peer message") + " {" + _("event message: ") + event['message'] + ", " + _("ip address: ")\ - + event['ip'] + ", " + _("client: ") + event['client_ID'] + "}" - if self.log_files: - log = os.path.join(self.logdir, 'peer_messages.log') - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_INVALID_REQUEST']: - event_message = _("Invalid request") + " {" + _("event message: ") + event['message'] + ", " + _("client: ")\ - + event['client_ID'] + "}" - if self.log_files: - log = os.path.join(self.logdir, 'invalid_requests.log') - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_FILE_ERROR']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - event_message = _("File error") + " {" + _("event message: ") + event['message'] + ", " + _("torrent: ")\ - + torrent + "}" - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_HASH_FAILED_ERROR']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - event_message = _("Hash failed error") + " {" + _("event message: ") + event['message'] + ", "\ - + _("torrent: ") + torrent + ", "\ - + _("piece index: ") + str(event['piece_index']) + "}" - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_PEER_BAN_ERROR']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - event_message = _("Peer ban error") + " {" + _("event message: ") + event['message'] + ", " + _("ip address: ")\ - + event['ip'] + ", " + _("torrent: ") + torrent + "}" - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_FASTRESUME_REJECTED_ERROR']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - event_message = _("Fastresume rejected error") + event['message'] + ", "\ - + _("torrent: ") + torrent + "}" - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_TRACKER_ANNOUNCE']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - event_message = _("Tracker announce") + " {" + _("event message: ") + event['message'] + ", "\ - + _("torrent: ") + torrent + "}" - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_TRACKER_REPLY']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - event_message = _("Tracker reply") + " {" + _("event message: ") + event['message'] + ", "\ - + _("torrent: ") + torrent + "}" - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_TRACKER_ALERT']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - try: - event_message = _("Tracker alert") + " {" + _("event message: ") + event['message'] + ", "\ - + _("torrent: ") + torrent + ", "\ - + _("status code: ") + str(event['status_code']) + ", " + _("Times in a row: ")\ - + str(event['times_in_row']) + "}" - except UnicodeDecodeError: - event_message = _("Unicode error") - else: - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_TRACKER_WARNING']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - try: - event_message = _("Tracker warning") + " {" + _("event message: ") + event['message'] + ", "\ - + _("torrent: ") + torrent + "}" - except UnicodeDecodeError: - event_message = _("Unicode error") - else: - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_STORAGE_MOVED']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - event_message = _("Storage moved") + " {" + _("event message: ") + event['message'] + ", "\ - + _("torrent: ") + torrent + "}" - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_PIECE_FINISHED']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - event_message = _("Piece finished") + " {" + _("event message: ") + event['message'] + ", "\ - + _("torrent: ") + torrent + ", "\ - + _("piece index: ") + str(event['piece_index']) + "}" - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_BLOCK_DOWNLOADING']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - event_message = _("Block downloading") + " {" + _("event message: ") + event['message'] + ", "\ - + _("torrent: ") + torrent + ", "\ - + _("piece index: ") + str(event['piece_index']) + ", " + _("block index: ")\ - + str(event['block_index']) + ", " + _("peer speed: ") + event['peer_speed'] + "}" - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_BLOCK_FINISHED']: - torrent = self.manager.unique_IDs[event['unique_ID']].filename.replace(os.path.join(common.CONFIG_DIR, 'torrentfiles/'), '') - event_message = _("Block finished") + " {" + _("event message: ") + event['message'] + ", "\ - + _("torrent: ") + torrent + ", "\ - + _("piece index: ") + str(event['piece_index']) + ", " + _("block index: ")\ - + str(event['block_index']) + "}" - if self.log_files: - log = os.path.join(self.logdir, torrent.replace('.torrent', '.log')) - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_PEER_BLOCKED']: - event_message = _("Peer blocked") + " {" + _("event message: ") + event['message'] + ", "\ - + _("ip address: ") + event['ip'] + "}" - if self.log_files: - log = os.path.join(self.logdir, 'peer_blocked.log') - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if event['event_type'] is self.manager.constants['EVENT_OTHER']: - try: - event_message = _("Other") + " {" + _("event message: ") + event['message'] + "}" - except UnicodeDecodeError: - event_message = _("Unicode error") - else: - if self.log_files: - log = os.path.join(self.logdir, 'other.log') - logfile = open(log, "a") - logfile.write(time.asctime(time.localtime()) + ", " +event_message + '\n') - logfile.close() - if not event_message is None: - label = gtk.Label() - self.labels.append(label) - label.set_text(event_message) - label.set_alignment(0,0) - label.set_selectable(True) - self.vbox.pack_end(label, expand=False) - if len(self.labels)>100: - remove_label = self.labels.pop(0) - remove_label.destroy() - label.show() diff --git a/plugins/FlexRSS/CalendarButton.py b/plugins/FlexRSS/CalendarButton.py deleted file mode 100644 index 2dea91f98..000000000 --- a/plugins/FlexRSS/CalendarButton.py +++ /dev/null @@ -1,67 +0,0 @@ -# Obviously needs work, but a decent start. -# Public domain - -import gobject, gtk, time - -class CalendarButton(gtk.Button): - format = None - calendar = None - window = None - - __gsignals__ = { - 'date-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), - 'date-selected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)) - } - - def __lost_focus(self, win, e): - print e.type - - def __day_selected(self, calendar): - self.window.hide() - newdate = self.get_date() - self.set_date(newdate[0], newdate[1], newdate[2]) - self.emit("date-selected", newdate) - - def __show_calendar(self, source): - if self.window != None: - self.window.show() - return - - self.window = gtk.Window(gtk.WINDOW_POPUP) - self.window.set_position(gtk.WIN_POS_MOUSE) - self.window.set_destroy_with_parent(True) - self.window.set_transient_for(source.get_ancestor(gtk.Window)) - self.window.add(self.calendar) - self.window.show_all() - - def __set_date_on_button(self, year, month, day): - self.set_label(time.strftime('%x', time.strptime('%d/%d/%d' % (day, month, year), '%d/%m/%Y'))) - - def set_date(self, year, month, day): - self.__set_date_on_button(year, month, day) - self.calendar.select_month(month - 1, year) - self.calendar.select_day(day) - self.emit("date-changed", (year, month, day)) - - def get_date(self): - ret = self.calendar.get_date() - return (ret[0], ret[1] + 1, ret[2]) - - def __init__(self, year=None, month=None, day=None): - value = time.localtime() - - if year == None: - year = value[0] - if month == None: - month = value[1] - if day == None: - day = value[2] - - self.calendar = gtk.Calendar() - self.calendar.select_month(month - 1, year) - self.calendar.select_day(day) - self.calendar.connect("day-selected-double-click", self.__day_selected) - - gtk.Button.__init__(self, time.strftime('%x', time.strptime('%d/%d/%d' % (day, month, year), '%d/%m/%Y'))) - - self.connect("pressed", self.__show_calendar) diff --git a/plugins/FlexRSS/FlexRSS.glade b/plugins/FlexRSS/FlexRSS.glade deleted file mode 100644 index ed5051452..000000000 --- a/plugins/FlexRSS/FlexRSS.glade +++ /dev/null @@ -1,1593 +0,0 @@ - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - FlexRSS - FlexRSS.svg - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-new - True - 0 - - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-save - True - 0 - - - - 1 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-delete - True - 0 - - - - 2 - - - - - False - 1 - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 4 - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Feed will be retrieved automatically, based on the update interval. - Enabled - 0 - True - True - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Feed must be refreshed manually. - Disabled - 0 - True - True - FlexRSS_EditFeed_Status_Enabled - - - 1 - - - - - 1 - 2 - 3 - 4 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Status - - - 3 - 4 - GTK_FILL - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Update Interval - - - 2 - 3 - GTK_FILL - GTK_FILL - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - URL - - - 1 - 2 - GTK_FILL - GTK_FILL - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Name - - - GTK_FILL - GTK_FILL - 5 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 900 - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - GTK_FILL - - - - - False - 2 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Feeds - - - tab - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-add - True - 0 - - - - False - False - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-delete - True - 0 - - - - False - False - 1 - - - - - False - 1 - - - - - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - 2 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Name - - - GTK_FILL - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Type - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Feed - - - 2 - 3 - GTK_FILL - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - False - - - - - 1 - 2 - 2 - 3 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Information</b> - True - - - label_item - - - - - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-add - True - 0 - - - - False - 1 - - - - - 1 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Patterns</b> - True - - - label_item - - - - - False - 1 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 5 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - From - 0 - True - - - - GTK_FILL - GTK_FILL - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Season - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - - 2 - 3 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Episode - - - 3 - 4 - GTK_FILL - GTK_FILL - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - - 4 - 5 - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Thru - 0 - True - - - - 1 - 2 - GTK_FILL - GTK_FILL - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Season - - - 1 - 2 - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - - 2 - 3 - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Episode - - - 3 - 4 - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - False - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - - 4 - 5 - 1 - 2 - GTK_FILL - - - - - False - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 2 - - - - - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - From - 0 - True - - - - GTK_FILL - GTK_FILL - 5 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Thru - 0 - True - - - - 1 - 2 - GTK_FILL - GTK_FILL - 5 - - - - - 1 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>History Restriction</b> - True - - - label_item - - - - - False - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Doesn't Match - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Season - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Episode - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - - - 1 - 2 - 1 - 2 - - - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Year - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Month - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Day - - - 2 - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - - - 1 - 2 - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - - - 1 - 2 - 2 - 3 - - - - - 1 - - - - - 1 - - - - - 1 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Test</b> - True - - - label_item - - - - - False - 3 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Insert torrent at top of queue. - 0 - True - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Set state to paused. - 0 - True - - - 1 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Delete filter when matched. - 0 - True - - - 2 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Download</b> - True - - - label_item - - - - - False - 4 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 2 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Replacement - - - 1 - 2 - GTK_FILL - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Pattern - - - GTK_FILL - 5 - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Link Rewriting</b> - True - - - label_item - - - - - False - 5 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Content will be saved to Deluge's default directory, or a prompt will appear if none is set. - Deluge default - 0 - True - True - FlexRSS_Filter_Output_Type_Custom - - - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Content will be automatically downloaded to the specified directory. - Choose: - 0 - True - True - - - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER - - - - False - 2 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Output</b> - True - - - label_item - - - - - False - 6 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-save - True - 0 - - - - False - 1 - - - - - False - GTK_PACK_END - 6 - - - - - 5 - 1 - - - - - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Filters - - - tab - 1 - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Show a FlexRSS icon in Deluge's toolbar. - Show button on toolbar. - 0 - True - - - - False - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Interface</b> - True - - - label_item - - - - - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Feeds will be retrieved and parsed in their own threads. The application will not be blocked, but it can be unreliable. - Threaded (experimental) - 0 - True - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Feed Retrieval</b> - True - - - label_item - - - - - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-new - True - 0 - - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-save - True - 0 - - - - 1 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-delete - True - 0 - - - - 2 - - - - - False - 1 - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 4 - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Domain - - - GTK_FILL - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Path - - - 1 - 2 - GTK_FILL - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Name - - - 2 - 3 - GTK_FILL - 5 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Value - - - 3 - 4 - GTK_FILL - 5 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 2 - 3 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 3 - 4 - - - - - False - 2 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Cookies</b> - True - - - label_item - - - - - 2 - - - - - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Configuration - - - tab - 2 - False - - - - - - diff --git a/plugins/FlexRSS/FlexRSS.png b/plugins/FlexRSS/FlexRSS.png deleted file mode 100644 index e27f1a464..000000000 Binary files a/plugins/FlexRSS/FlexRSS.png and /dev/null differ diff --git a/plugins/FlexRSS/__init__.py b/plugins/FlexRSS/__init__.py deleted file mode 100644 index 89ab7b865..000000000 --- a/plugins/FlexRSS/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -FlexRSS_DEFAULTS = { - 'VERSION': (0, 2, 3) -} - -plugin_name = "FlexRSS" -plugin_author = "Daddy" -plugin_version = "%d.%d.%d" % (FlexRSS_DEFAULTS['VERSION'][0], FlexRSS_DEFAULTS['VERSION'][1], FlexRSS_DEFAULTS['VERSION'][2]) -plugin_description = _(""" -Advanced RSS scraper - -This plugin is similar in purpose to Mark Adamson's excellent RSS Broadcatcher, but targets a more advanced audience. It is extremely powerful, configurable, unforgiving, and difficult. - -Filters use regular expressions with named patterns and strptime(3)-like format filters to match items. - -For more information and documentation, visit http://dev.deluge-torrent.org/wiki/Plugins/FlexRSS""") - -from FlexRSS.plugin import plugin_FlexRSS - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return plugin_FlexRSS(path, core, interface, FlexRSS_DEFAULTS) diff --git a/plugins/FlexRSS/feedparser.py b/plugins/FlexRSS/feedparser.py deleted file mode 100644 index bb802df16..000000000 --- a/plugins/FlexRSS/feedparser.py +++ /dev/null @@ -1,2858 +0,0 @@ -#!/usr/bin/env python -"""Universal feed parser - -Handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds - -Visit http://feedparser.org/ for the latest version -Visit http://feedparser.org/docs/ for the latest documentation - -Required: Python 2.1 or later -Recommended: Python 2.3 or later -Recommended: CJKCodecs and iconv_codec -""" - -__version__ = "4.1"# + "$Revision: 1.92 $"[11:15] + "-cvs" -__license__ = """Copyright (c) 2002-2006, Mark Pilgrim, All rights reserved. - -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. - -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.""" -__author__ = "Mark Pilgrim " -__contributors__ = ["Jason Diamond ", - "John Beimler ", - "Fazal Majid ", - "Aaron Swartz ", - "Kevin Marks "] -_debug = 0 - -# HTTP "User-Agent" header to send to servers when downloading feeds. -# If you are embedding feedparser in a larger application, you should -# change this to your application name and URL. -USER_AGENT = "UniversalFeedParser/%s +http://feedparser.org/" % __version__ - -# HTTP "Accept" header to send to servers when downloading feeds. If you don't -# want to send an Accept header, set this to None. -ACCEPT_HEADER = "application/atom+xml,application/rdf+xml,application/rss+xml,application/x-netcdf,application/xml;q=0.9,text/xml;q=0.2,*/*;q=0.1" - -# List of preferred XML parsers, by SAX driver name. These will be tried first, -# but if they're not installed, Python will keep searching through its own list -# of pre-installed parsers until it finds one that supports everything we need. -PREFERRED_XML_PARSERS = ["drv_libxml2"] - -# If you want feedparser to automatically run HTML markup through HTML Tidy, set -# this to 1. Requires mxTidy -# or utidylib . -TIDY_MARKUP = 0 - -# List of Python interfaces for HTML Tidy, in order of preference. Only useful -# if TIDY_MARKUP = 1 -PREFERRED_TIDY_INTERFACES = ["uTidy", "mxTidy"] - -# ---------- required modules (should come with any Python distribution) ---------- -import sgmllib, re, sys, copy, urlparse, time, rfc822, types, cgi, urllib, urllib2 -try: - from cStringIO import StringIO as _StringIO -except: - from StringIO import StringIO as _StringIO - -# ---------- optional modules (feedparser will work without these, but with reduced functionality) ---------- - -# gzip is included with most Python distributions, but may not be available if you compiled your own -try: - import gzip -except: - gzip = None -try: - import zlib -except: - zlib = None - -# If a real XML parser is available, feedparser will attempt to use it. feedparser has -# been tested with the built-in SAX parser, PyXML, and libxml2. On platforms where the -# Python distribution does not come with an XML parser (such as Mac OS X 10.2 and some -# versions of FreeBSD), feedparser will quietly fall back on regex-based parsing. -try: - import xml.sax - xml.sax.make_parser(PREFERRED_XML_PARSERS) # test for valid parsers - from xml.sax.saxutils import escape as _xmlescape - _XML_AVAILABLE = 1 -except: - _XML_AVAILABLE = 0 - def _xmlescape(data): - data = data.replace('&', '&') - data = data.replace('>', '>') - data = data.replace('<', '<') - return data - -# base64 support for Atom feeds that contain embedded binary data -try: - import base64, binascii -except: - base64 = binascii = None - -# cjkcodecs and iconv_codec provide support for more character encodings. -# Both are available from http://cjkpython.i18n.org/ -try: - import cjkcodecs.aliases -except: - pass -try: - import iconv_codec -except: - pass - -# chardet library auto-detects character encodings -# Download from http://chardet.feedparser.org/ -try: - import chardet - if _debug: - import chardet.constants - chardet.constants._debug = 1 -except: - chardet = None - -# ---------- don't touch these ---------- -class ThingsNobodyCaresAboutButMe(Exception): pass -class CharacterEncodingOverride(ThingsNobodyCaresAboutButMe): pass -class CharacterEncodingUnknown(ThingsNobodyCaresAboutButMe): pass -class NonXMLContentType(ThingsNobodyCaresAboutButMe): pass -class UndeclaredNamespace(Exception): pass - -sgmllib.tagfind = re.compile('[a-zA-Z][-_.:a-zA-Z0-9]*') -sgmllib.special = re.compile('' % (tag, ''.join([' %s="%s"' % t for t in attrs])), escape=0) - - # match namespaces - if tag.find(':') <> -1: - prefix, suffix = tag.split(':', 1) - else: - prefix, suffix = '', tag - prefix = self.namespacemap.get(prefix, prefix) - if prefix: - prefix = prefix + '_' - - # special hack for better tracking of empty textinput/image elements in illformed feeds - if (not prefix) and tag not in ('title', 'link', 'description', 'name'): - self.intextinput = 0 - if (not prefix) and tag not in ('title', 'link', 'description', 'url', 'href', 'width', 'height'): - self.inimage = 0 - - # call special handler (if defined) or default handler - methodname = '_start_' + prefix + suffix - try: - method = getattr(self, methodname) - return method(attrsD) - except AttributeError: - return self.push(prefix + suffix, 1) - - def unknown_endtag(self, tag): - if _debug: sys.stderr.write('end %s\n' % tag) - # match namespaces - if tag.find(':') <> -1: - prefix, suffix = tag.split(':', 1) - else: - prefix, suffix = '', tag - prefix = self.namespacemap.get(prefix, prefix) - if prefix: - prefix = prefix + '_' - - # call special handler (if defined) or default handler - methodname = '_end_' + prefix + suffix - try: - method = getattr(self, methodname) - method() - except AttributeError: - self.pop(prefix + suffix) - - # track inline content - if self.incontent and self.contentparams.has_key('type') and not self.contentparams.get('type', 'xml').endswith('xml'): - # element declared itself as escaped markup, but it isn't really - self.contentparams['type'] = 'application/xhtml+xml' - if self.incontent and self.contentparams.get('type') == 'application/xhtml+xml': - tag = tag.split(':')[-1] - self.handle_data('' % tag, escape=0) - - # track xml:base and xml:lang going out of scope - if self.basestack: - self.basestack.pop() - if self.basestack and self.basestack[-1]: - self.baseuri = self.basestack[-1] - if self.langstack: - self.langstack.pop() - if self.langstack: # and (self.langstack[-1] is not None): - self.lang = self.langstack[-1] - - def handle_charref(self, ref): - # called for each character reference, e.g. for ' ', ref will be '160' - if not self.elementstack: return - ref = ref.lower() - if ref in ('34', '38', '39', '60', '62', 'x22', 'x26', 'x27', 'x3c', 'x3e'): - text = '&#%s;' % ref - else: - if ref[0] == 'x': - c = int(ref[1:], 16) - else: - c = int(ref) - text = unichr(c).encode('utf-8') - self.elementstack[-1][2].append(text) - - def handle_entityref(self, ref): - # called for each entity reference, e.g. for '©', ref will be 'copy' - if not self.elementstack: return - if _debug: sys.stderr.write('entering handle_entityref with %s\n' % ref) - if ref in ('lt', 'gt', 'quot', 'amp', 'apos'): - text = '&%s;' % ref - else: - # entity resolution graciously donated by Aaron Swartz - def name2cp(k): - import htmlentitydefs - if hasattr(htmlentitydefs, 'name2codepoint'): # requires Python 2.3 - return htmlentitydefs.name2codepoint[k] - k = htmlentitydefs.entitydefs[k] - if k.startswith('&#') and k.endswith(';'): - return int(k[2:-1]) # not in latin-1 - return ord(k) - try: name2cp(ref) - except KeyError: text = '&%s;' % ref - else: text = unichr(name2cp(ref)).encode('utf-8') - self.elementstack[-1][2].append(text) - - def handle_data(self, text, escape=1): - # called for each block of plain text, i.e. outside of any tag and - # not containing any character or entity references - if not self.elementstack: return - if escape and self.contentparams.get('type') == 'application/xhtml+xml': - text = _xmlescape(text) - self.elementstack[-1][2].append(text) - - def handle_comment(self, text): - # called for each comment, e.g. - pass - - def handle_pi(self, text): - # called for each processing instruction, e.g. - pass - - def handle_decl(self, text): - pass - - def parse_declaration(self, i): - # override internal declaration handler to handle CDATA blocks - if _debug: sys.stderr.write('entering parse_declaration\n') - if self.rawdata[i:i+9] == '', i) - if k == -1: k = len(self.rawdata) - self.handle_data(_xmlescape(self.rawdata[i+9:k]), 0) - return k+3 - else: - k = self.rawdata.find('>', i) - return k+1 - - def mapContentType(self, contentType): - contentType = contentType.lower() - if contentType == 'text': - contentType = 'text/plain' - elif contentType == 'html': - contentType = 'text/html' - elif contentType == 'xhtml': - contentType = 'application/xhtml+xml' - return contentType - - def trackNamespace(self, prefix, uri): - loweruri = uri.lower() - if (prefix, loweruri) == (None, 'http://my.netscape.com/rdf/simple/0.9/') and not self.version: - self.version = 'rss090' - if loweruri == 'http://purl.org/rss/1.0/' and not self.version: - self.version = 'rss10' - if loweruri == 'http://www.w3.org/2005/atom' and not self.version: - self.version = 'atom10' - if loweruri.find('backend.userland.com/rss') <> -1: - # match any backend.userland.com namespace - uri = 'http://backend.userland.com/rss' - loweruri = uri - if self._matchnamespaces.has_key(loweruri): - self.namespacemap[prefix] = self._matchnamespaces[loweruri] - self.namespacesInUse[self._matchnamespaces[loweruri]] = uri - else: - self.namespacesInUse[prefix or ''] = uri - - def resolveURI(self, uri): - return _urljoin(self.baseuri or '', uri) - - def decodeEntities(self, element, data): - return data - - def push(self, element, expectingText): - self.elementstack.append([element, expectingText, []]) - - def pop(self, element, stripWhitespace=1): - if not self.elementstack: return - if self.elementstack[-1][0] != element: return - - element, expectingText, pieces = self.elementstack.pop() - output = ''.join(pieces) - if stripWhitespace: - output = output.strip() - if not expectingText: return output - - # decode base64 content - if base64 and self.contentparams.get('base64', 0): - try: - output = base64.decodestring(output) - except binascii.Error: - pass - except binascii.Incomplete: - pass - - # resolve relative URIs - if (element in self.can_be_relative_uri) and output: - output = self.resolveURI(output) - - # decode entities within embedded markup - if not self.contentparams.get('base64', 0): - output = self.decodeEntities(element, output) - - # remove temporary cruft from contentparams - try: - del self.contentparams['mode'] - except KeyError: - pass - try: - del self.contentparams['base64'] - except KeyError: - pass - - # resolve relative URIs within embedded markup - if self.mapContentType(self.contentparams.get('type', 'text/html')) in self.html_types: - if element in self.can_contain_relative_uris: - output = _resolveRelativeURIs(output, self.baseuri, self.encoding) - - # sanitize embedded markup - if self.mapContentType(self.contentparams.get('type', 'text/html')) in self.html_types: - if element in self.can_contain_dangerous_markup: - output = _sanitizeHTML(output, self.encoding) - - if self.encoding and type(output) != type(u''): - try: - output = unicode(output, self.encoding) - except: - pass - - # categories/tags/keywords/whatever are handled in _end_category - if element == 'category': - return output - - # store output in appropriate place(s) - if self.inentry and not self.insource: - if element == 'content': - self.entries[-1].setdefault(element, []) - contentparams = copy.deepcopy(self.contentparams) - contentparams['value'] = output - self.entries[-1][element].append(contentparams) - elif element == 'link': - self.entries[-1][element] = output - if output: - self.entries[-1]['links'][-1]['href'] = output - else: - if element == 'description': - element = 'summary' - self.entries[-1][element] = output - if self.incontent: - contentparams = copy.deepcopy(self.contentparams) - contentparams['value'] = output - self.entries[-1][element + '_detail'] = contentparams - elif (self.infeed or self.insource) and (not self.intextinput) and (not self.inimage): - context = self._getContext() - if element == 'description': - element = 'subtitle' - context[element] = output - if element == 'link': - context['links'][-1]['href'] = output - elif self.incontent: - contentparams = copy.deepcopy(self.contentparams) - contentparams['value'] = output - context[element + '_detail'] = contentparams - return output - - def pushContent(self, tag, attrsD, defaultContentType, expectingText): - self.incontent += 1 - self.contentparams = FeedParserDict({ - 'type': self.mapContentType(attrsD.get('type', defaultContentType)), - 'language': self.lang, - 'base': self.baseuri}) - self.contentparams['base64'] = self._isBase64(attrsD, self.contentparams) - self.push(tag, expectingText) - - def popContent(self, tag): - value = self.pop(tag) - self.incontent -= 1 - self.contentparams.clear() - return value - - def _mapToStandardPrefix(self, name): - colonpos = name.find(':') - if colonpos <> -1: - prefix = name[:colonpos] - suffix = name[colonpos+1:] - prefix = self.namespacemap.get(prefix, prefix) - name = prefix + ':' + suffix - return name - - def _getAttribute(self, attrsD, name): - return attrsD.get(self._mapToStandardPrefix(name)) - - def _isBase64(self, attrsD, contentparams): - if attrsD.get('mode', '') == 'base64': - return 1 - if self.contentparams['type'].startswith('text/'): - return 0 - if self.contentparams['type'].endswith('+xml'): - return 0 - if self.contentparams['type'].endswith('/xml'): - return 0 - return 1 - - def _itsAnHrefDamnIt(self, attrsD): - href = attrsD.get('url', attrsD.get('uri', attrsD.get('href', None))) - if href: - try: - del attrsD['url'] - except KeyError: - pass - try: - del attrsD['uri'] - except KeyError: - pass - attrsD['href'] = href - return attrsD - - def _save(self, key, value): - context = self._getContext() - context.setdefault(key, value) - - def _start_rss(self, attrsD): - versionmap = {'0.91': 'rss091u', - '0.92': 'rss092', - '0.93': 'rss093', - '0.94': 'rss094'} - if not self.version: - attr_version = attrsD.get('version', '') - version = versionmap.get(attr_version) - if version: - self.version = version - elif attr_version.startswith('2.'): - self.version = 'rss20' - else: - self.version = 'rss' - - def _start_dlhottitles(self, attrsD): - self.version = 'hotrss' - - def _start_channel(self, attrsD): - self.infeed = 1 - self._cdf_common(attrsD) - _start_feedinfo = _start_channel - - def _cdf_common(self, attrsD): - if attrsD.has_key('lastmod'): - self._start_modified({}) - self.elementstack[-1][-1] = attrsD['lastmod'] - self._end_modified() - if attrsD.has_key('href'): - self._start_link({}) - self.elementstack[-1][-1] = attrsD['href'] - self._end_link() - - def _start_feed(self, attrsD): - self.infeed = 1 - versionmap = {'0.1': 'atom01', - '0.2': 'atom02', - '0.3': 'atom03'} - if not self.version: - attr_version = attrsD.get('version') - version = versionmap.get(attr_version) - if version: - self.version = version - else: - self.version = 'atom' - - def _end_channel(self): - self.infeed = 0 - _end_feed = _end_channel - - def _start_image(self, attrsD): - self.inimage = 1 - self.push('image', 0) - context = self._getContext() - context.setdefault('image', FeedParserDict()) - - def _end_image(self): - self.pop('image') - self.inimage = 0 - - def _start_textinput(self, attrsD): - self.intextinput = 1 - self.push('textinput', 0) - context = self._getContext() - context.setdefault('textinput', FeedParserDict()) - _start_textInput = _start_textinput - - def _end_textinput(self): - self.pop('textinput') - self.intextinput = 0 - _end_textInput = _end_textinput - - def _start_author(self, attrsD): - self.inauthor = 1 - self.push('author', 1) - _start_managingeditor = _start_author - _start_dc_author = _start_author - _start_dc_creator = _start_author - _start_itunes_author = _start_author - - def _end_author(self): - self.pop('author') - self.inauthor = 0 - self._sync_author_detail() - _end_managingeditor = _end_author - _end_dc_author = _end_author - _end_dc_creator = _end_author - _end_itunes_author = _end_author - - def _start_itunes_owner(self, attrsD): - self.inpublisher = 1 - self.push('publisher', 0) - - def _end_itunes_owner(self): - self.pop('publisher') - self.inpublisher = 0 - self._sync_author_detail('publisher') - - def _start_contributor(self, attrsD): - self.incontributor = 1 - context = self._getContext() - context.setdefault('contributors', []) - context['contributors'].append(FeedParserDict()) - self.push('contributor', 0) - - def _end_contributor(self): - self.pop('contributor') - self.incontributor = 0 - - def _start_dc_contributor(self, attrsD): - self.incontributor = 1 - context = self._getContext() - context.setdefault('contributors', []) - context['contributors'].append(FeedParserDict()) - self.push('name', 0) - - def _end_dc_contributor(self): - self._end_name() - self.incontributor = 0 - - def _start_name(self, attrsD): - self.push('name', 0) - _start_itunes_name = _start_name - - def _end_name(self): - value = self.pop('name') - if self.inpublisher: - self._save_author('name', value, 'publisher') - elif self.inauthor: - self._save_author('name', value) - elif self.incontributor: - self._save_contributor('name', value) - elif self.intextinput: - context = self._getContext() - context['textinput']['name'] = value - _end_itunes_name = _end_name - - def _start_width(self, attrsD): - self.push('width', 0) - - def _end_width(self): - value = self.pop('width') - try: - value = int(value) - except: - value = 0 - if self.inimage: - context = self._getContext() - context['image']['width'] = value - - def _start_height(self, attrsD): - self.push('height', 0) - - def _end_height(self): - value = self.pop('height') - try: - value = int(value) - except: - value = 0 - if self.inimage: - context = self._getContext() - context['image']['height'] = value - - def _start_url(self, attrsD): - self.push('href', 1) - _start_homepage = _start_url - _start_uri = _start_url - - def _end_url(self): - value = self.pop('href') - if self.inauthor: - self._save_author('href', value) - elif self.incontributor: - self._save_contributor('href', value) - elif self.inimage: - context = self._getContext() - context['image']['href'] = value - elif self.intextinput: - context = self._getContext() - context['textinput']['link'] = value - _end_homepage = _end_url - _end_uri = _end_url - - def _start_email(self, attrsD): - self.push('email', 0) - _start_itunes_email = _start_email - - def _end_email(self): - value = self.pop('email') - if self.inpublisher: - self._save_author('email', value, 'publisher') - elif self.inauthor: - self._save_author('email', value) - elif self.incontributor: - self._save_contributor('email', value) - _end_itunes_email = _end_email - - def _getContext(self): - if self.insource: - context = self.sourcedata - elif self.inentry: - context = self.entries[-1] - else: - context = self.feeddata - return context - - def _save_author(self, key, value, prefix='author'): - context = self._getContext() - context.setdefault(prefix + '_detail', FeedParserDict()) - context[prefix + '_detail'][key] = value - self._sync_author_detail() - - def _save_contributor(self, key, value): - context = self._getContext() - context.setdefault('contributors', [FeedParserDict()]) - context['contributors'][-1][key] = value - - def _sync_author_detail(self, key='author'): - context = self._getContext() - detail = context.get('%s_detail' % key) - if detail: - name = detail.get('name') - email = detail.get('email') - if name and email: - context[key] = '%s (%s)' % (name, email) - elif name: - context[key] = name - elif email: - context[key] = email - else: - author = context.get(key) - if not author: return - emailmatch = re.search(r'''(([a-zA-Z0-9\_\-\.\+]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?))''', author) - if not emailmatch: return - email = emailmatch.group(0) - # probably a better way to do the following, but it passes all the tests - author = author.replace(email, '') - author = author.replace('()', '') - author = author.strip() - if author and (author[0] == '('): - author = author[1:] - if author and (author[-1] == ')'): - author = author[:-1] - author = author.strip() - context.setdefault('%s_detail' % key, FeedParserDict()) - context['%s_detail' % key]['name'] = author - context['%s_detail' % key]['email'] = email - - def _start_subtitle(self, attrsD): - self.pushContent('subtitle', attrsD, 'text/plain', 1) - _start_tagline = _start_subtitle - _start_itunes_subtitle = _start_subtitle - - def _end_subtitle(self): - self.popContent('subtitle') - _end_tagline = _end_subtitle - _end_itunes_subtitle = _end_subtitle - - def _start_rights(self, attrsD): - self.pushContent('rights', attrsD, 'text/plain', 1) - _start_dc_rights = _start_rights - _start_copyright = _start_rights - - def _end_rights(self): - self.popContent('rights') - _end_dc_rights = _end_rights - _end_copyright = _end_rights - - def _start_item(self, attrsD): - self.entries.append(FeedParserDict()) - self.push('item', 0) - self.inentry = 1 - self.guidislink = 0 - id = self._getAttribute(attrsD, 'rdf:about') - if id: - context = self._getContext() - context['id'] = id - self._cdf_common(attrsD) - _start_entry = _start_item - _start_product = _start_item - - def _end_item(self): - self.pop('item') - self.inentry = 0 - _end_entry = _end_item - - def _start_dc_language(self, attrsD): - self.push('language', 1) - _start_language = _start_dc_language - - def _end_dc_language(self): - self.lang = self.pop('language') - _end_language = _end_dc_language - - def _start_dc_publisher(self, attrsD): - self.push('publisher', 1) - _start_webmaster = _start_dc_publisher - - def _end_dc_publisher(self): - self.pop('publisher') - self._sync_author_detail('publisher') - _end_webmaster = _end_dc_publisher - - def _start_published(self, attrsD): - self.push('published', 1) - _start_dcterms_issued = _start_published - _start_issued = _start_published - - def _end_published(self): - value = self.pop('published') - self._save('published_parsed', _parse_date(value)) - _end_dcterms_issued = _end_published - _end_issued = _end_published - - def _start_updated(self, attrsD): - self.push('updated', 1) - _start_modified = _start_updated - _start_dcterms_modified = _start_updated - _start_pubdate = _start_updated - _start_dc_date = _start_updated - - def _end_updated(self): - value = self.pop('updated') - parsed_value = _parse_date(value) - self._save('updated_parsed', parsed_value) - _end_modified = _end_updated - _end_dcterms_modified = _end_updated - _end_pubdate = _end_updated - _end_dc_date = _end_updated - - def _start_created(self, attrsD): - self.push('created', 1) - _start_dcterms_created = _start_created - - def _end_created(self): - value = self.pop('created') - self._save('created_parsed', _parse_date(value)) - _end_dcterms_created = _end_created - - def _start_expirationdate(self, attrsD): - self.push('expired', 1) - - def _end_expirationdate(self): - self._save('expired_parsed', _parse_date(self.pop('expired'))) - - def _start_cc_license(self, attrsD): - self.push('license', 1) - value = self._getAttribute(attrsD, 'rdf:resource') - if value: - self.elementstack[-1][2].append(value) - self.pop('license') - - def _start_creativecommons_license(self, attrsD): - self.push('license', 1) - - def _end_creativecommons_license(self): - self.pop('license') - - def _addTag(self, term, scheme, label): - context = self._getContext() - tags = context.setdefault('tags', []) - if (not term) and (not scheme) and (not label): return - value = FeedParserDict({'term': term, 'scheme': scheme, 'label': label}) - if value not in tags: - tags.append(FeedParserDict({'term': term, 'scheme': scheme, 'label': label})) - - def _start_category(self, attrsD): - if _debug: sys.stderr.write('entering _start_category with %s\n' % repr(attrsD)) - term = attrsD.get('term') - scheme = attrsD.get('scheme', attrsD.get('domain')) - label = attrsD.get('label') - self._addTag(term, scheme, label) - self.push('category', 1) - _start_dc_subject = _start_category - _start_keywords = _start_category - - def _end_itunes_keywords(self): - for term in self.pop('itunes_keywords').split(): - self._addTag(term, 'http://www.itunes.com/', None) - - def _start_itunes_category(self, attrsD): - self._addTag(attrsD.get('text'), 'http://www.itunes.com/', None) - self.push('category', 1) - - def _end_category(self): - value = self.pop('category') - if not value: return - context = self._getContext() - tags = context['tags'] - if value and len(tags) and not tags[-1]['term']: - tags[-1]['term'] = value - else: - self._addTag(value, None, None) - _end_dc_subject = _end_category - _end_keywords = _end_category - _end_itunes_category = _end_category - - def _start_cloud(self, attrsD): - self._getContext()['cloud'] = FeedParserDict(attrsD) - - def _start_link(self, attrsD): - attrsD.setdefault('rel', 'alternate') - attrsD.setdefault('type', 'text/html') - attrsD = self._itsAnHrefDamnIt(attrsD) - if attrsD.has_key('href'): - attrsD['href'] = self.resolveURI(attrsD['href']) - expectingText = self.infeed or self.inentry or self.insource - context = self._getContext() - context.setdefault('links', []) - context['links'].append(FeedParserDict(attrsD)) - if attrsD['rel'] == 'enclosure': - self._start_enclosure(attrsD) - if attrsD.has_key('href'): - expectingText = 0 - if (attrsD.get('rel') == 'alternate') and (self.mapContentType(attrsD.get('type')) in self.html_types): - context['link'] = attrsD['href'] - else: - self.push('link', expectingText) - _start_producturl = _start_link - - def _end_link(self): - value = self.pop('link') - context = self._getContext() - if self.intextinput: - context['textinput']['link'] = value - if self.inimage: - context['image']['link'] = value - _end_producturl = _end_link - - def _start_guid(self, attrsD): - self.guidislink = (attrsD.get('ispermalink', 'true') == 'true') - self.push('id', 1) - - def _end_guid(self): - value = self.pop('id') - self._save('guidislink', self.guidislink and not self._getContext().has_key('link')) - if self.guidislink: - # guid acts as link, but only if 'ispermalink' is not present or is 'true', - # and only if the item doesn't already have a link element - self._save('link', value) - - def _start_title(self, attrsD): - self.pushContent('title', attrsD, 'text/plain', self.infeed or self.inentry or self.insource) - _start_dc_title = _start_title - _start_media_title = _start_title - - def _end_title(self): - value = self.popContent('title') - context = self._getContext() - if self.intextinput: - context['textinput']['title'] = value - elif self.inimage: - context['image']['title'] = value - _end_dc_title = _end_title - _end_media_title = _end_title - - def _start_description(self, attrsD): - context = self._getContext() - if context.has_key('summary'): - self._summaryKey = 'content' - self._start_content(attrsD) - else: - self.pushContent('description', attrsD, 'text/html', self.infeed or self.inentry or self.insource) - - def _start_abstract(self, attrsD): - self.pushContent('description', attrsD, 'text/plain', self.infeed or self.inentry or self.insource) - - def _end_description(self): - if self._summaryKey == 'content': - self._end_content() - else: - value = self.popContent('description') - context = self._getContext() - if self.intextinput: - context['textinput']['description'] = value - elif self.inimage: - context['image']['description'] = value - self._summaryKey = None - _end_abstract = _end_description - - def _start_info(self, attrsD): - self.pushContent('info', attrsD, 'text/plain', 1) - _start_feedburner_browserfriendly = _start_info - - def _end_info(self): - self.popContent('info') - _end_feedburner_browserfriendly = _end_info - - def _start_generator(self, attrsD): - if attrsD: - attrsD = self._itsAnHrefDamnIt(attrsD) - if attrsD.has_key('href'): - attrsD['href'] = self.resolveURI(attrsD['href']) - self._getContext()['generator_detail'] = FeedParserDict(attrsD) - self.push('generator', 1) - - def _end_generator(self): - value = self.pop('generator') - context = self._getContext() - if context.has_key('generator_detail'): - context['generator_detail']['name'] = value - - def _start_admin_generatoragent(self, attrsD): - self.push('generator', 1) - value = self._getAttribute(attrsD, 'rdf:resource') - if value: - self.elementstack[-1][2].append(value) - self.pop('generator') - self._getContext()['generator_detail'] = FeedParserDict({'href': value}) - - def _start_admin_errorreportsto(self, attrsD): - self.push('errorreportsto', 1) - value = self._getAttribute(attrsD, 'rdf:resource') - if value: - self.elementstack[-1][2].append(value) - self.pop('errorreportsto') - - def _start_summary(self, attrsD): - context = self._getContext() - if context.has_key('summary'): - self._summaryKey = 'content' - self._start_content(attrsD) - else: - self._summaryKey = 'summary' - self.pushContent(self._summaryKey, attrsD, 'text/plain', 1) - _start_itunes_summary = _start_summary - - def _end_summary(self): - if self._summaryKey == 'content': - self._end_content() - else: - self.popContent(self._summaryKey or 'summary') - self._summaryKey = None - _end_itunes_summary = _end_summary - - def _start_enclosure(self, attrsD): - attrsD = self._itsAnHrefDamnIt(attrsD) - self._getContext().setdefault('enclosures', []).append(FeedParserDict(attrsD)) - href = attrsD.get('href') - if href: - context = self._getContext() - if not context.get('id'): - context['id'] = href - - def _start_source(self, attrsD): - self.insource = 1 - - def _end_source(self): - self.insource = 0 - self._getContext()['source'] = copy.deepcopy(self.sourcedata) - self.sourcedata.clear() - - def _start_content(self, attrsD): - self.pushContent('content', attrsD, 'text/plain', 1) - src = attrsD.get('src') - if src: - self.contentparams['src'] = src - self.push('content', 1) - - def _start_prodlink(self, attrsD): - self.pushContent('content', attrsD, 'text/html', 1) - - def _start_body(self, attrsD): - self.pushContent('content', attrsD, 'application/xhtml+xml', 1) - _start_xhtml_body = _start_body - - def _start_content_encoded(self, attrsD): - self.pushContent('content', attrsD, 'text/html', 1) - _start_fullitem = _start_content_encoded - - def _end_content(self): - copyToDescription = self.mapContentType(self.contentparams.get('type')) in (['text/plain'] + self.html_types) - value = self.popContent('content') - if copyToDescription: - self._save('description', value) - _end_body = _end_content - _end_xhtml_body = _end_content - _end_content_encoded = _end_content - _end_fullitem = _end_content - _end_prodlink = _end_content - - def _start_itunes_image(self, attrsD): - self.push('itunes_image', 0) - self._getContext()['image'] = FeedParserDict({'href': attrsD.get('href')}) - _start_itunes_link = _start_itunes_image - - def _end_itunes_block(self): - value = self.pop('itunes_block', 0) - self._getContext()['itunes_block'] = (value == 'yes') and 1 or 0 - - def _end_itunes_explicit(self): - value = self.pop('itunes_explicit', 0) - self._getContext()['itunes_explicit'] = (value == 'yes') and 1 or 0 - -if _XML_AVAILABLE: - class _StrictFeedParser(_FeedParserMixin, xml.sax.handler.ContentHandler): - def __init__(self, baseuri, baselang, encoding): - if _debug: sys.stderr.write('trying StrictFeedParser\n') - xml.sax.handler.ContentHandler.__init__(self) - _FeedParserMixin.__init__(self, baseuri, baselang, encoding) - self.bozo = 0 - self.exc = None - - def startPrefixMapping(self, prefix, uri): - self.trackNamespace(prefix, uri) - - def startElementNS(self, name, qname, attrs): - namespace, localname = name - lowernamespace = str(namespace or '').lower() - if lowernamespace.find('backend.userland.com/rss') <> -1: - # match any backend.userland.com namespace - namespace = 'http://backend.userland.com/rss' - lowernamespace = namespace - if qname and qname.find(':') > 0: - givenprefix = qname.split(':')[0] - else: - givenprefix = None - prefix = self._matchnamespaces.get(lowernamespace, givenprefix) - if givenprefix and (prefix == None or (prefix == '' and lowernamespace == '')) and not self.namespacesInUse.has_key(givenprefix): - raise UndeclaredNamespace, "'%s' is not associated with a namespace" % givenprefix - if prefix: - localname = prefix + ':' + localname - localname = str(localname).lower() - if _debug: sys.stderr.write('startElementNS: qname = %s, namespace = %s, givenprefix = %s, prefix = %s, attrs = %s, localname = %s\n' % (qname, namespace, givenprefix, prefix, attrs.items(), localname)) - - # qname implementation is horribly broken in Python 2.1 (it - # doesn't report any), and slightly broken in Python 2.2 (it - # doesn't report the xml: namespace). So we match up namespaces - # with a known list first, and then possibly override them with - # the qnames the SAX parser gives us (if indeed it gives us any - # at all). Thanks to MatejC for helping me test this and - # tirelessly telling me that it didn't work yet. - attrsD = {} - for (namespace, attrlocalname), attrvalue in attrs._attrs.items(): - lowernamespace = (namespace or '').lower() - prefix = self._matchnamespaces.get(lowernamespace, '') - if prefix: - attrlocalname = prefix + ':' + attrlocalname - attrsD[str(attrlocalname).lower()] = attrvalue - for qname in attrs.getQNames(): - attrsD[str(qname).lower()] = attrs.getValueByQName(qname) - self.unknown_starttag(localname, attrsD.items()) - - def characters(self, text): - self.handle_data(text) - - def endElementNS(self, name, qname): - namespace, localname = name - lowernamespace = str(namespace or '').lower() - if qname and qname.find(':') > 0: - givenprefix = qname.split(':')[0] - else: - givenprefix = '' - prefix = self._matchnamespaces.get(lowernamespace, givenprefix) - if prefix: - localname = prefix + ':' + localname - localname = str(localname).lower() - self.unknown_endtag(localname) - - def error(self, exc): - self.bozo = 1 - self.exc = exc - - def fatalError(self, exc): - self.error(exc) - raise exc - -class _BaseHTMLProcessor(sgmllib.SGMLParser): - elements_no_end_tag = ['area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', - 'img', 'input', 'isindex', 'link', 'meta', 'param'] - - def __init__(self, encoding): - self.encoding = encoding - if _debug: sys.stderr.write('entering BaseHTMLProcessor, encoding=%s\n' % self.encoding) - sgmllib.SGMLParser.__init__(self) - - def reset(self): - self.pieces = [] - sgmllib.SGMLParser.reset(self) - - def _shorttag_replace(self, match): - tag = match.group(1) - if tag in self.elements_no_end_tag: - return '<' + tag + ' />' - else: - return '<' + tag + '>' - - def feed(self, data): - data = re.compile(r'', self._shorttag_replace, data) # bug [ 1399464 ] Bad regexp for _shorttag_replace - data = re.sub(r'<([^<\s]+?)\s*/>', self._shorttag_replace, data) - data = data.replace(''', "'") - data = data.replace('"', '"') - if self.encoding and type(data) == type(u''): - data = data.encode(self.encoding) - sgmllib.SGMLParser.feed(self, data) - - def normalize_attrs(self, attrs): - # utility method to be called by descendants - attrs = [(k.lower(), v) for k, v in attrs] - attrs = [(k, k in ('rel', 'type') and v.lower() or v) for k, v in attrs] - return attrs - - def unknown_starttag(self, tag, attrs): - # called for each start tag - # attrs is a list of (attr, value) tuples - # e.g. for
        , tag='pre', attrs=[('class', 'screen')]
        -        if _debug: sys.stderr.write('_BaseHTMLProcessor, unknown_starttag, tag=%s\n' % tag)
        -        uattrs = []
        -        # thanks to Kevin Marks for this breathtaking hack to deal with (valid) high-bit attribute values in UTF-8 feeds
        -        for key, value in attrs:
        -            if type(value) != type(u''):
        -                value = unicode(value, self.encoding)
        -            uattrs.append((unicode(key, self.encoding), value))
        -        strattrs = u''.join([u' %s="%s"' % (key, value) for key, value in uattrs]).encode(self.encoding)
        -        if tag in self.elements_no_end_tag:
        -            self.pieces.append('<%(tag)s%(strattrs)s />' % locals())
        -        else:
        -            self.pieces.append('<%(tag)s%(strattrs)s>' % locals())
        -
        -    def unknown_endtag(self, tag):
        -        # called for each end tag, e.g. for 
        , tag will be 'pre' - # Reconstruct the original end tag. - if tag not in self.elements_no_end_tag: - self.pieces.append("" % locals()) - - def handle_charref(self, ref): - # called for each character reference, e.g. for ' ', ref will be '160' - # Reconstruct the original character reference. - self.pieces.append('&#%(ref)s;' % locals()) - - def handle_entityref(self, ref): - # called for each entity reference, e.g. for '©', ref will be 'copy' - # Reconstruct the original entity reference. - self.pieces.append('&%(ref)s;' % locals()) - - def handle_data(self, text): - # called for each block of plain text, i.e. outside of any tag and - # not containing any character or entity references - # Store the original text verbatim. - if _debug: sys.stderr.write('_BaseHTMLProcessor, handle_text, text=%s\n' % text) - self.pieces.append(text) - - def handle_comment(self, text): - # called for each HTML comment, e.g. - # Reconstruct the original comment. - self.pieces.append('' % locals()) - - def handle_pi(self, text): - # called for each processing instruction, e.g. - # Reconstruct original processing instruction. - self.pieces.append('' % locals()) - - def handle_decl(self, text): - # called for the DOCTYPE, if present, e.g. - # - # Reconstruct original DOCTYPE - self.pieces.append('' % locals()) - - _new_declname_match = re.compile(r'[a-zA-Z][-_.a-zA-Z0-9:]*\s*').match - def _scan_name(self, i, declstartpos): - rawdata = self.rawdata - n = len(rawdata) - if i == n: - return None, -1 - m = self._new_declname_match(rawdata, i) - if m: - s = m.group() - name = s.strip() - if (i + len(s)) == n: - return None, -1 # end of buffer - return name.lower(), m.end() - else: - self.handle_data(rawdata) -# self.updatepos(declstartpos, i) - return None, -1 - - def output(self): - '''Return processed HTML as a single string''' - return ''.join([str(p) for p in self.pieces]) - -class _LooseFeedParser(_FeedParserMixin, _BaseHTMLProcessor): - def __init__(self, baseuri, baselang, encoding): - sgmllib.SGMLParser.__init__(self) - _FeedParserMixin.__init__(self, baseuri, baselang, encoding) - - def decodeEntities(self, element, data): - data = data.replace('<', '<') - data = data.replace('<', '<') - data = data.replace('>', '>') - data = data.replace('>', '>') - data = data.replace('&', '&') - data = data.replace('&', '&') - data = data.replace('"', '"') - data = data.replace('"', '"') - data = data.replace(''', ''') - data = data.replace(''', ''') - if self.contentparams.has_key('type') and not self.contentparams.get('type', 'xml').endswith('xml'): - data = data.replace('<', '<') - data = data.replace('>', '>') - data = data.replace('&', '&') - data = data.replace('"', '"') - data = data.replace(''', "'") - return data - -class _RelativeURIResolver(_BaseHTMLProcessor): - relative_uris = [('a', 'href'), - ('applet', 'codebase'), - ('area', 'href'), - ('blockquote', 'cite'), - ('body', 'background'), - ('del', 'cite'), - ('form', 'action'), - ('frame', 'longdesc'), - ('frame', 'src'), - ('iframe', 'longdesc'), - ('iframe', 'src'), - ('head', 'profile'), - ('img', 'longdesc'), - ('img', 'src'), - ('img', 'usemap'), - ('input', 'src'), - ('input', 'usemap'), - ('ins', 'cite'), - ('link', 'href'), - ('object', 'classid'), - ('object', 'codebase'), - ('object', 'data'), - ('object', 'usemap'), - ('q', 'cite'), - ('script', 'src')] - - def __init__(self, baseuri, encoding): - _BaseHTMLProcessor.__init__(self, encoding) - self.baseuri = baseuri - - def resolveURI(self, uri): - return _urljoin(self.baseuri, uri) - - def unknown_starttag(self, tag, attrs): - attrs = self.normalize_attrs(attrs) - attrs = [(key, ((tag, key) in self.relative_uris) and self.resolveURI(value) or value) for key, value in attrs] - _BaseHTMLProcessor.unknown_starttag(self, tag, attrs) - -def _resolveRelativeURIs(htmlSource, baseURI, encoding): - if _debug: sys.stderr.write('entering _resolveRelativeURIs\n') - p = _RelativeURIResolver(baseURI, encoding) - p.feed(htmlSource) - return p.output() - -class _HTMLSanitizer(_BaseHTMLProcessor): - acceptable_elements = ['a', 'abbr', 'acronym', 'address', 'area', 'b', 'big', - 'blockquote', 'br', 'button', 'caption', 'center', 'cite', 'code', 'col', - 'colgroup', 'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt', 'em', 'fieldset', - 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'input', - 'ins', 'kbd', 'label', 'legend', 'li', 'map', 'menu', 'ol', 'optgroup', - 'option', 'p', 'pre', 'q', 's', 'samp', 'select', 'small', 'span', 'strike', - 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', - 'thead', 'tr', 'tt', 'u', 'ul', 'var'] - - acceptable_attributes = ['abbr', 'accept', 'accept-charset', 'accesskey', - 'action', 'align', 'alt', 'axis', 'border', 'cellpadding', 'cellspacing', - 'char', 'charoff', 'charset', 'checked', 'cite', 'class', 'clear', 'cols', - 'colspan', 'color', 'compact', 'coords', 'datetime', 'dir', 'disabled', - 'enctype', 'for', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', - 'id', 'ismap', 'label', 'lang', 'longdesc', 'maxlength', 'media', 'method', - 'multiple', 'name', 'nohref', 'noshade', 'nowrap', 'prompt', 'readonly', - 'rel', 'rev', 'rows', 'rowspan', 'rules', 'scope', 'selected', 'shape', 'size', - 'span', 'src', 'start', 'summary', 'tabindex', 'target', 'title', 'type', - 'usemap', 'valign', 'value', 'vspace', 'width'] - - unacceptable_elements_with_end_tag = ['script', 'applet'] - - def reset(self): - _BaseHTMLProcessor.reset(self) - self.unacceptablestack = 0 - - def unknown_starttag(self, tag, attrs): - if not tag in self.acceptable_elements: - if tag in self.unacceptable_elements_with_end_tag: - self.unacceptablestack += 1 - return - attrs = self.normalize_attrs(attrs) - attrs = [(key, value) for key, value in attrs if key in self.acceptable_attributes] - _BaseHTMLProcessor.unknown_starttag(self, tag, attrs) - - def unknown_endtag(self, tag): - if not tag in self.acceptable_elements: - if tag in self.unacceptable_elements_with_end_tag: - self.unacceptablestack -= 1 - return - _BaseHTMLProcessor.unknown_endtag(self, tag) - - def handle_pi(self, text): - pass - - def handle_decl(self, text): - pass - - def handle_data(self, text): - if not self.unacceptablestack: - _BaseHTMLProcessor.handle_data(self, text) - -def _sanitizeHTML(htmlSource, encoding): - p = _HTMLSanitizer(encoding) - p.feed(htmlSource) - data = p.output() - if TIDY_MARKUP: - # loop through list of preferred Tidy interfaces looking for one that's installed, - # then set up a common _tidy function to wrap the interface-specific API. - _tidy = None - for tidy_interface in PREFERRED_TIDY_INTERFACES: - try: - if tidy_interface == "uTidy": - from tidy import parseString as _utidy - def _tidy(data, **kwargs): - return str(_utidy(data, **kwargs)) - break - elif tidy_interface == "mxTidy": - from mx.Tidy import Tidy as _mxtidy - def _tidy(data, **kwargs): - nerrors, nwarnings, data, errordata = _mxtidy.tidy(data, **kwargs) - return data - break - except: - pass - if _tidy: - utf8 = type(data) == type(u'') - if utf8: - data = data.encode('utf-8') - data = _tidy(data, output_xhtml=1, numeric_entities=1, wrap=0, char_encoding="utf8") - if utf8: - data = unicode(data, 'utf-8') - if data.count(''): - data = data.split('>', 1)[1] - if data.count('= '2.3.3' - assert base64 != None - user, passw = base64.decodestring(req.headers['Authorization'].split(' ')[1]).split(':') - realm = re.findall('realm="([^"]*)"', headers['WWW-Authenticate'])[0] - self.add_password(realm, host, user, passw) - retry = self.http_error_auth_reqed('www-authenticate', host, req, headers) - self.reset_retry_count() - return retry - except: - return self.http_error_default(req, fp, code, msg, headers) - -def _open_resource(url_file_stream_or_string, etag, modified, agent, referrer, handlers): - """URL, filename, or string --> stream - - This function lets you define parsers that take any input source - (URL, pathname to local or network file, or actual data as a string) - and deal with it in a uniform manner. Returned object is guaranteed - to have all the basic stdio read methods (read, readline, readlines). - Just .close() the object when you're done with it. - - If the etag argument is supplied, it will be used as the value of an - If-None-Match request header. - - If the modified argument is supplied, it must be a tuple of 9 integers - as returned by gmtime() in the standard Python time module. This MUST - be in GMT (Greenwich Mean Time). The formatted date/time will be used - as the value of an If-Modified-Since request header. - - If the agent argument is supplied, it will be used as the value of a - User-Agent request header. - - If the referrer argument is supplied, it will be used as the value of a - Referer[sic] request header. - - If handlers is supplied, it is a list of handlers used to build a - urllib2 opener. - """ - - if hasattr(url_file_stream_or_string, 'read'): - return url_file_stream_or_string - - if url_file_stream_or_string == '-': - return sys.stdin - - if urlparse.urlparse(url_file_stream_or_string)[0] in ('http', 'https', 'ftp'): - if not agent: - agent = USER_AGENT - # test for inline user:password for basic auth - auth = None - if base64: - urltype, rest = urllib.splittype(url_file_stream_or_string) - realhost, rest = urllib.splithost(rest) - if realhost: - user_passwd, realhost = urllib.splituser(realhost) - if user_passwd: - url_file_stream_or_string = '%s://%s%s' % (urltype, realhost, rest) - auth = base64.encodestring(user_passwd).strip() - # try to open with urllib2 (to use optional headers) - request = urllib2.Request(url_file_stream_or_string) - request.add_header('User-Agent', agent) - if etag: - request.add_header('If-None-Match', etag) - if modified: - # format into an RFC 1123-compliant timestamp. We can't use - # time.strftime() since the %a and %b directives can be affected - # by the current locale, but RFC 2616 states that dates must be - # in English. - short_weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] - months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] - request.add_header('If-Modified-Since', '%s, %02d %s %04d %02d:%02d:%02d GMT' % (short_weekdays[modified[6]], modified[2], months[modified[1] - 1], modified[0], modified[3], modified[4], modified[5])) - if referrer: - request.add_header('Referer', referrer) - if gzip and zlib: - request.add_header('Accept-encoding', 'gzip, deflate') - elif gzip: - request.add_header('Accept-encoding', 'gzip') - elif zlib: - request.add_header('Accept-encoding', 'deflate') - else: - request.add_header('Accept-encoding', '') - if auth: - request.add_header('Authorization', 'Basic %s' % auth) - if ACCEPT_HEADER: - request.add_header('Accept', ACCEPT_HEADER) - request.add_header('A-IM', 'feed') # RFC 3229 support - opener = apply(urllib2.build_opener, tuple([_FeedURLHandler()] + handlers)) - opener.addheaders = [] # RMK - must clear so we only send our custom User-Agent - try: - return opener.open(request) - finally: - opener.close() # JohnD - - # try to open with native open function (if url_file_stream_or_string is a filename) - try: - return open(url_file_stream_or_string) - except: - pass - - # treat url_file_stream_or_string as string - return _StringIO(str(url_file_stream_or_string)) - -_date_handlers = [] -def registerDateHandler(func): - '''Register a date handler function (takes string, returns 9-tuple date in GMT)''' - _date_handlers.insert(0, func) - -# ISO-8601 date parsing routines written by Fazal Majid. -# The ISO 8601 standard is very convoluted and irregular - a full ISO 8601 -# parser is beyond the scope of feedparser and would be a worthwhile addition -# to the Python library. -# A single regular expression cannot parse ISO 8601 date formats into groups -# as the standard is highly irregular (for instance is 030104 2003-01-04 or -# 0301-04-01), so we use templates instead. -# Please note the order in templates is significant because we need a -# greedy match. -_iso8601_tmpl = ['YYYY-?MM-?DD', 'YYYY-MM', 'YYYY-?OOO', - 'YY-?MM-?DD', 'YY-?OOO', 'YYYY', - '-YY-?MM', '-OOO', '-YY', - '--MM-?DD', '--MM', - '---DD', - 'CC', ''] -_iso8601_re = [ - tmpl.replace( - 'YYYY', r'(?P\d{4})').replace( - 'YY', r'(?P\d\d)').replace( - 'MM', r'(?P[01]\d)').replace( - 'DD', r'(?P[0123]\d)').replace( - 'OOO', r'(?P[0123]\d\d)').replace( - 'CC', r'(?P\d\d$)') - + r'(T?(?P\d{2}):(?P\d{2})' - + r'(:(?P\d{2}))?' - + r'(?P[+-](?P\d{2})(:(?P\d{2}))?|Z)?)?' - for tmpl in _iso8601_tmpl] -del tmpl -_iso8601_matches = [re.compile(regex).match for regex in _iso8601_re] -del regex -def _parse_date_iso8601(dateString): - '''Parse a variety of ISO-8601-compatible formats like 20040105''' - m = None - for _iso8601_match in _iso8601_matches: - m = _iso8601_match(dateString) - if m: break - if not m: return - if m.span() == (0, 0): return - params = m.groupdict() - ordinal = params.get('ordinal', 0) - if ordinal: - ordinal = int(ordinal) - else: - ordinal = 0 - year = params.get('year', '--') - if not year or year == '--': - year = time.gmtime()[0] - elif len(year) == 2: - # ISO 8601 assumes current century, i.e. 93 -> 2093, NOT 1993 - year = 100 * int(time.gmtime()[0] / 100) + int(year) - else: - year = int(year) - month = params.get('month', '-') - if not month or month == '-': - # ordinals are NOT normalized by mktime, we simulate them - # by setting month=1, day=ordinal - if ordinal: - month = 1 - else: - month = time.gmtime()[1] - month = int(month) - day = params.get('day', 0) - if not day: - # see above - if ordinal: - day = ordinal - elif params.get('century', 0) or \ - params.get('year', 0) or params.get('month', 0): - day = 1 - else: - day = time.gmtime()[2] - else: - day = int(day) - # special case of the century - is the first year of the 21st century - # 2000 or 2001 ? The debate goes on... - if 'century' in params.keys(): - year = (int(params['century']) - 1) * 100 + 1 - # in ISO 8601 most fields are optional - for field in ['hour', 'minute', 'second', 'tzhour', 'tzmin']: - if not params.get(field, None): - params[field] = 0 - hour = int(params.get('hour', 0)) - minute = int(params.get('minute', 0)) - second = int(params.get('second', 0)) - # weekday is normalized by mktime(), we can ignore it - weekday = 0 - # daylight savings is complex, but not needed for feedparser's purposes - # as time zones, if specified, include mention of whether it is active - # (e.g. PST vs. PDT, CET). Using -1 is implementation-dependent and - # and most implementations have DST bugs - daylight_savings_flag = 0 - tm = [year, month, day, hour, minute, second, weekday, - ordinal, daylight_savings_flag] - # ISO 8601 time zone adjustments - tz = params.get('tz') - if tz and tz != 'Z': - if tz[0] == '-': - tm[3] += int(params.get('tzhour', 0)) - tm[4] += int(params.get('tzmin', 0)) - elif tz[0] == '+': - tm[3] -= int(params.get('tzhour', 0)) - tm[4] -= int(params.get('tzmin', 0)) - else: - return None - # Python's time.mktime() is a wrapper around the ANSI C mktime(3c) - # which is guaranteed to normalize d/m/y/h/m/s. - # Many implementations have bugs, but we'll pretend they don't. - return time.localtime(time.mktime(tm)) -registerDateHandler(_parse_date_iso8601) - -# 8-bit date handling routines written by ytrewq1. -_korean_year = u'\ub144' # b3e2 in euc-kr -_korean_month = u'\uc6d4' # bff9 in euc-kr -_korean_day = u'\uc77c' # c0cf in euc-kr -_korean_am = u'\uc624\uc804' # bfc0 c0fc in euc-kr -_korean_pm = u'\uc624\ud6c4' # bfc0 c8c4 in euc-kr - -_korean_onblog_date_re = \ - re.compile('(\d{4})%s\s+(\d{2})%s\s+(\d{2})%s\s+(\d{2}):(\d{2}):(\d{2})' % \ - (_korean_year, _korean_month, _korean_day)) -_korean_nate_date_re = \ - re.compile(u'(\d{4})-(\d{2})-(\d{2})\s+(%s|%s)\s+(\d{,2}):(\d{,2}):(\d{,2})' % \ - (_korean_am, _korean_pm)) -def _parse_date_onblog(dateString): - '''Parse a string according to the OnBlog 8-bit date format''' - m = _korean_onblog_date_re.match(dateString) - if not m: return - w3dtfdate = '%(year)s-%(month)s-%(day)sT%(hour)s:%(minute)s:%(second)s%(zonediff)s' % \ - {'year': m.group(1), 'month': m.group(2), 'day': m.group(3),\ - 'hour': m.group(4), 'minute': m.group(5), 'second': m.group(6),\ - 'zonediff': '+09:00'} - if _debug: sys.stderr.write('OnBlog date parsed as: %s\n' % w3dtfdate) - return _parse_date_w3dtf(w3dtfdate) -registerDateHandler(_parse_date_onblog) - -def _parse_date_nate(dateString): - '''Parse a string according to the Nate 8-bit date format''' - m = _korean_nate_date_re.match(dateString) - if not m: return - hour = int(m.group(5)) - ampm = m.group(4) - if (ampm == _korean_pm): - hour += 12 - hour = str(hour) - if len(hour) == 1: - hour = '0' + hour - w3dtfdate = '%(year)s-%(month)s-%(day)sT%(hour)s:%(minute)s:%(second)s%(zonediff)s' % \ - {'year': m.group(1), 'month': m.group(2), 'day': m.group(3),\ - 'hour': hour, 'minute': m.group(6), 'second': m.group(7),\ - 'zonediff': '+09:00'} - if _debug: sys.stderr.write('Nate date parsed as: %s\n' % w3dtfdate) - return _parse_date_w3dtf(w3dtfdate) -registerDateHandler(_parse_date_nate) - -_mssql_date_re = \ - re.compile('(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})(\.\d+)?') -def _parse_date_mssql(dateString): - '''Parse a string according to the MS SQL date format''' - m = _mssql_date_re.match(dateString) - if not m: return - w3dtfdate = '%(year)s-%(month)s-%(day)sT%(hour)s:%(minute)s:%(second)s%(zonediff)s' % \ - {'year': m.group(1), 'month': m.group(2), 'day': m.group(3),\ - 'hour': m.group(4), 'minute': m.group(5), 'second': m.group(6),\ - 'zonediff': '+09:00'} - if _debug: sys.stderr.write('MS SQL date parsed as: %s\n' % w3dtfdate) - return _parse_date_w3dtf(w3dtfdate) -registerDateHandler(_parse_date_mssql) - -# Unicode strings for Greek date strings -_greek_months = \ - { \ - u'\u0399\u03b1\u03bd': u'Jan', # c9e1ed in iso-8859-7 - u'\u03a6\u03b5\u03b2': u'Feb', # d6e5e2 in iso-8859-7 - u'\u039c\u03ac\u03ce': u'Mar', # ccdcfe in iso-8859-7 - u'\u039c\u03b1\u03ce': u'Mar', # cce1fe in iso-8859-7 - u'\u0391\u03c0\u03c1': u'Apr', # c1f0f1 in iso-8859-7 - u'\u039c\u03ac\u03b9': u'May', # ccdce9 in iso-8859-7 - u'\u039c\u03b1\u03ca': u'May', # cce1fa in iso-8859-7 - u'\u039c\u03b1\u03b9': u'May', # cce1e9 in iso-8859-7 - u'\u0399\u03bf\u03cd\u03bd': u'Jun', # c9effded in iso-8859-7 - u'\u0399\u03bf\u03bd': u'Jun', # c9efed in iso-8859-7 - u'\u0399\u03bf\u03cd\u03bb': u'Jul', # c9effdeb in iso-8859-7 - u'\u0399\u03bf\u03bb': u'Jul', # c9f9eb in iso-8859-7 - u'\u0391\u03cd\u03b3': u'Aug', # c1fde3 in iso-8859-7 - u'\u0391\u03c5\u03b3': u'Aug', # c1f5e3 in iso-8859-7 - u'\u03a3\u03b5\u03c0': u'Sep', # d3e5f0 in iso-8859-7 - u'\u039f\u03ba\u03c4': u'Oct', # cfeaf4 in iso-8859-7 - u'\u039d\u03bf\u03ad': u'Nov', # cdefdd in iso-8859-7 - u'\u039d\u03bf\u03b5': u'Nov', # cdefe5 in iso-8859-7 - u'\u0394\u03b5\u03ba': u'Dec', # c4e5ea in iso-8859-7 - } - -_greek_wdays = \ - { \ - u'\u039a\u03c5\u03c1': u'Sun', # caf5f1 in iso-8859-7 - u'\u0394\u03b5\u03c5': u'Mon', # c4e5f5 in iso-8859-7 - u'\u03a4\u03c1\u03b9': u'Tue', # d4f1e9 in iso-8859-7 - u'\u03a4\u03b5\u03c4': u'Wed', # d4e5f4 in iso-8859-7 - u'\u03a0\u03b5\u03bc': u'Thu', # d0e5ec in iso-8859-7 - u'\u03a0\u03b1\u03c1': u'Fri', # d0e1f1 in iso-8859-7 - u'\u03a3\u03b1\u03b2': u'Sat', # d3e1e2 in iso-8859-7 - } - -_greek_date_format_re = \ - re.compile(u'([^,]+),\s+(\d{2})\s+([^\s]+)\s+(\d{4})\s+(\d{2}):(\d{2}):(\d{2})\s+([^\s]+)') - -def _parse_date_greek(dateString): - '''Parse a string according to a Greek 8-bit date format.''' - m = _greek_date_format_re.match(dateString) - if not m: return - try: - wday = _greek_wdays[m.group(1)] - month = _greek_months[m.group(3)] - except: - return - rfc822date = '%(wday)s, %(day)s %(month)s %(year)s %(hour)s:%(minute)s:%(second)s %(zonediff)s' % \ - {'wday': wday, 'day': m.group(2), 'month': month, 'year': m.group(4),\ - 'hour': m.group(5), 'minute': m.group(6), 'second': m.group(7),\ - 'zonediff': m.group(8)} - if _debug: sys.stderr.write('Greek date parsed as: %s\n' % rfc822date) - return _parse_date_rfc822(rfc822date) -registerDateHandler(_parse_date_greek) - -# Unicode strings for Hungarian date strings -_hungarian_months = \ - { \ - u'janu\u00e1r': u'01', # e1 in iso-8859-2 - u'febru\u00e1ri': u'02', # e1 in iso-8859-2 - u'm\u00e1rcius': u'03', # e1 in iso-8859-2 - u'\u00e1prilis': u'04', # e1 in iso-8859-2 - u'm\u00e1ujus': u'05', # e1 in iso-8859-2 - u'j\u00fanius': u'06', # fa in iso-8859-2 - u'j\u00falius': u'07', # fa in iso-8859-2 - u'augusztus': u'08', - u'szeptember': u'09', - u'okt\u00f3ber': u'10', # f3 in iso-8859-2 - u'november': u'11', - u'december': u'12', - } - -_hungarian_date_format_re = \ - re.compile(u'(\d{4})-([^-]+)-(\d{,2})T(\d{,2}):(\d{2})((\+|-)(\d{,2}:\d{2}))') - -def _parse_date_hungarian(dateString): - '''Parse a string according to a Hungarian 8-bit date format.''' - m = _hungarian_date_format_re.match(dateString) - if not m: return - try: - month = _hungarian_months[m.group(2)] - day = m.group(3) - if len(day) == 1: - day = '0' + day - hour = m.group(4) - if len(hour) == 1: - hour = '0' + hour - except: - return - w3dtfdate = '%(year)s-%(month)s-%(day)sT%(hour)s:%(minute)s%(zonediff)s' % \ - {'year': m.group(1), 'month': month, 'day': day,\ - 'hour': hour, 'minute': m.group(5),\ - 'zonediff': m.group(6)} - if _debug: sys.stderr.write('Hungarian date parsed as: %s\n' % w3dtfdate) - return _parse_date_w3dtf(w3dtfdate) -registerDateHandler(_parse_date_hungarian) - -# W3DTF-style date parsing adapted from PyXML xml.utils.iso8601, written by -# Drake and licensed under the Python license. Removed all range checking -# for month, day, hour, minute, and second, since mktime will normalize -# these later -def _parse_date_w3dtf(dateString): - def __extract_date(m): - year = int(m.group('year')) - if year < 100: - year = 100 * int(time.gmtime()[0] / 100) + int(year) - if year < 1000: - return 0, 0, 0 - julian = m.group('julian') - if julian: - julian = int(julian) - month = julian / 30 + 1 - day = julian % 30 + 1 - jday = None - while jday != julian: - t = time.mktime((year, month, day, 0, 0, 0, 0, 0, 0)) - jday = time.gmtime(t)[-2] - diff = abs(jday - julian) - if jday > julian: - if diff < day: - day = day - diff - else: - month = month - 1 - day = 31 - elif jday < julian: - if day + diff < 28: - day = day + diff - else: - month = month + 1 - return year, month, day - month = m.group('month') - day = 1 - if month is None: - month = 1 - else: - month = int(month) - day = m.group('day') - if day: - day = int(day) - else: - day = 1 - return year, month, day - - def __extract_time(m): - if not m: - return 0, 0, 0 - hours = m.group('hours') - if not hours: - return 0, 0, 0 - hours = int(hours) - minutes = int(m.group('minutes')) - seconds = m.group('seconds') - if seconds: - seconds = int(seconds) - else: - seconds = 0 - return hours, minutes, seconds - - def __extract_tzd(m): - '''Return the Time Zone Designator as an offset in seconds from UTC.''' - if not m: - return 0 - tzd = m.group('tzd') - if not tzd: - return 0 - if tzd == 'Z': - return 0 - hours = int(m.group('tzdhours')) - minutes = m.group('tzdminutes') - if minutes: - minutes = int(minutes) - else: - minutes = 0 - offset = (hours*60 + minutes) * 60 - if tzd[0] == '+': - return -offset - return offset - - __date_re = ('(?P\d\d\d\d)' - '(?:(?P-|)' - '(?:(?P\d\d\d)' - '|(?P\d\d)(?:(?P=dsep)(?P\d\d))?))?') - __tzd_re = '(?P[-+](?P\d\d)(?::?(?P\d\d))|Z)' - __tzd_rx = re.compile(__tzd_re) - __time_re = ('(?P\d\d)(?P:|)(?P\d\d)' - '(?:(?P=tsep)(?P\d\d(?:[.,]\d+)?))?' - + __tzd_re) - __datetime_re = '%s(?:T%s)?' % (__date_re, __time_re) - __datetime_rx = re.compile(__datetime_re) - m = __datetime_rx.match(dateString) - if (m is None) or (m.group() != dateString): return - gmt = __extract_date(m) + __extract_time(m) + (0, 0, 0) - if gmt[0] == 0: return - return time.gmtime(time.mktime(gmt) + __extract_tzd(m) - time.timezone) -registerDateHandler(_parse_date_w3dtf) - -def _parse_date_rfc822(dateString): - '''Parse an RFC822, RFC1123, RFC2822, or asctime-style date''' - data = dateString.split() - if data[0][-1] in (',', '.') or data[0].lower() in rfc822._daynames: - del data[0] - if len(data) == 4: - s = data[3] - i = s.find('+') - if i > 0: - data[3:] = [s[:i], s[i+1:]] - else: - data.append('') - dateString = " ".join(data) - if len(data) < 5: - dateString += ' 00:00:00 GMT' - tm = rfc822.parsedate_tz(dateString) - if tm: - return time.gmtime(rfc822.mktime_tz(tm)) -# rfc822.py defines several time zones, but we define some extra ones. -# 'ET' is equivalent to 'EST', etc. -_additional_timezones = {'AT': -400, 'ET': -500, 'CT': -600, 'MT': -700, 'PT': -800} -rfc822._timezones.update(_additional_timezones) -registerDateHandler(_parse_date_rfc822) - -def _parse_date(dateString): - '''Parses a variety of date formats into a 9-tuple in GMT''' - for handler in _date_handlers: - try: - date9tuple = handler(dateString) - if not date9tuple: continue - if len(date9tuple) != 9: - if _debug: sys.stderr.write('date handler function must return 9-tuple\n') - raise ValueError - map(int, date9tuple) - return date9tuple - except Exception, e: - if _debug: sys.stderr.write('%s raised %s\n' % (handler.__name__, repr(e))) - pass - return None - -def _getCharacterEncoding(http_headers, xml_data): - '''Get the character encoding of the XML document - - http_headers is a dictionary - xml_data is a raw string (not Unicode) - - This is so much trickier than it sounds, it's not even funny. - According to RFC 3023 ('XML Media Types'), if the HTTP Content-Type - is application/xml, application/*+xml, - application/xml-external-parsed-entity, or application/xml-dtd, - the encoding given in the charset parameter of the HTTP Content-Type - takes precedence over the encoding given in the XML prefix within the - document, and defaults to 'utf-8' if neither are specified. But, if - the HTTP Content-Type is text/xml, text/*+xml, or - text/xml-external-parsed-entity, the encoding given in the XML prefix - within the document is ALWAYS IGNORED and only the encoding given in - the charset parameter of the HTTP Content-Type header should be - respected, and it defaults to 'us-ascii' if not specified. - - Furthermore, discussion on the atom-syntax mailing list with the - author of RFC 3023 leads me to the conclusion that any document - served with a Content-Type of text/* and no charset parameter - must be treated as us-ascii. (We now do this.) And also that it - must always be flagged as non-well-formed. (We now do this too.) - - If Content-Type is unspecified (input was local file or non-HTTP source) - or unrecognized (server just got it totally wrong), then go by the - encoding given in the XML prefix of the document and default to - 'iso-8859-1' as per the HTTP specification (RFC 2616). - - Then, assuming we didn't find a character encoding in the HTTP headers - (and the HTTP Content-type allowed us to look in the body), we need - to sniff the first few bytes of the XML data and try to determine - whether the encoding is ASCII-compatible. Section F of the XML - specification shows the way here: - http://www.w3.org/TR/REC-xml/#sec-guessing-no-ext-info - - If the sniffed encoding is not ASCII-compatible, we need to make it - ASCII compatible so that we can sniff further into the XML declaration - to find the encoding attribute, which will tell us the true encoding. - - Of course, none of this guarantees that we will be able to parse the - feed in the declared character encoding (assuming it was declared - correctly, which many are not). CJKCodecs and iconv_codec help a lot; - you should definitely install them if you can. - http://cjkpython.i18n.org/ - ''' - - def _parseHTTPContentType(content_type): - '''takes HTTP Content-Type header and returns (content type, charset) - - If no charset is specified, returns (content type, '') - If no content type is specified, returns ('', '') - Both return parameters are guaranteed to be lowercase strings - ''' - content_type = content_type or '' - content_type, params = cgi.parse_header(content_type) - return content_type, params.get('charset', '').replace("'", '') - - sniffed_xml_encoding = '' - xml_encoding = '' - true_encoding = '' - http_content_type, http_encoding = _parseHTTPContentType(http_headers.get('content-type')) - # Must sniff for non-ASCII-compatible character encodings before - # searching for XML declaration. This heuristic is defined in - # section F of the XML specification: - # http://www.w3.org/TR/REC-xml/#sec-guessing-no-ext-info - try: - if xml_data[:4] == '\x4c\x6f\xa7\x94': - # EBCDIC - xml_data = _ebcdic_to_ascii(xml_data) - elif xml_data[:4] == '\x00\x3c\x00\x3f': - # UTF-16BE - sniffed_xml_encoding = 'utf-16be' - xml_data = unicode(xml_data, 'utf-16be').encode('utf-8') - elif (len(xml_data) >= 4) and (xml_data[:2] == '\xfe\xff') and (xml_data[2:4] != '\x00\x00'): - # UTF-16BE with BOM - sniffed_xml_encoding = 'utf-16be' - xml_data = unicode(xml_data[2:], 'utf-16be').encode('utf-8') - elif xml_data[:4] == '\x3c\x00\x3f\x00': - # UTF-16LE - sniffed_xml_encoding = 'utf-16le' - xml_data = unicode(xml_data, 'utf-16le').encode('utf-8') - elif (len(xml_data) >= 4) and (xml_data[:2] == '\xff\xfe') and (xml_data[2:4] != '\x00\x00'): - # UTF-16LE with BOM - sniffed_xml_encoding = 'utf-16le' - xml_data = unicode(xml_data[2:], 'utf-16le').encode('utf-8') - elif xml_data[:4] == '\x00\x00\x00\x3c': - # UTF-32BE - sniffed_xml_encoding = 'utf-32be' - xml_data = unicode(xml_data, 'utf-32be').encode('utf-8') - elif xml_data[:4] == '\x3c\x00\x00\x00': - # UTF-32LE - sniffed_xml_encoding = 'utf-32le' - xml_data = unicode(xml_data, 'utf-32le').encode('utf-8') - elif xml_data[:4] == '\x00\x00\xfe\xff': - # UTF-32BE with BOM - sniffed_xml_encoding = 'utf-32be' - xml_data = unicode(xml_data[4:], 'utf-32be').encode('utf-8') - elif xml_data[:4] == '\xff\xfe\x00\x00': - # UTF-32LE with BOM - sniffed_xml_encoding = 'utf-32le' - xml_data = unicode(xml_data[4:], 'utf-32le').encode('utf-8') - elif xml_data[:3] == '\xef\xbb\xbf': - # UTF-8 with BOM - sniffed_xml_encoding = 'utf-8' - xml_data = unicode(xml_data[3:], 'utf-8').encode('utf-8') - else: - # ASCII-compatible - pass - xml_encoding_match = re.compile('^<\?.*encoding=[\'"](.*?)[\'"].*\?>').match(xml_data) - except: - xml_encoding_match = None - if xml_encoding_match: - xml_encoding = xml_encoding_match.groups()[0].lower() - if sniffed_xml_encoding and (xml_encoding in ('iso-10646-ucs-2', 'ucs-2', 'csunicode', 'iso-10646-ucs-4', 'ucs-4', 'csucs4', 'utf-16', 'utf-32', 'utf_16', 'utf_32', 'utf16', 'u16')): - xml_encoding = sniffed_xml_encoding - acceptable_content_type = 0 - application_content_types = ('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity') - text_content_types = ('text/xml', 'text/xml-external-parsed-entity') - if (http_content_type in application_content_types) or \ - (http_content_type.startswith('application/') and http_content_type.endswith('+xml')): - acceptable_content_type = 1 - true_encoding = http_encoding or xml_encoding or 'utf-8' - elif (http_content_type in text_content_types) or \ - (http_content_type.startswith('text/')) and http_content_type.endswith('+xml'): - acceptable_content_type = 1 - true_encoding = http_encoding or 'us-ascii' - elif http_content_type.startswith('text/'): - true_encoding = http_encoding or 'us-ascii' - elif http_headers and (not http_headers.has_key('content-type')): - true_encoding = xml_encoding or 'iso-8859-1' - else: - true_encoding = xml_encoding or 'utf-8' - return true_encoding, http_encoding, xml_encoding, sniffed_xml_encoding, acceptable_content_type - -def _toUTF8(data, encoding): - '''Changes an XML data stream on the fly to specify a new encoding - - data is a raw sequence of bytes (not Unicode) that is presumed to be in %encoding already - encoding is a string recognized by encodings.aliases - ''' - if _debug: sys.stderr.write('entering _toUTF8, trying encoding %s\n' % encoding) - # strip Byte Order Mark (if present) - if (len(data) >= 4) and (data[:2] == '\xfe\xff') and (data[2:4] != '\x00\x00'): - if _debug: - sys.stderr.write('stripping BOM\n') - if encoding != 'utf-16be': - sys.stderr.write('trying utf-16be instead\n') - encoding = 'utf-16be' - data = data[2:] - elif (len(data) >= 4) and (data[:2] == '\xff\xfe') and (data[2:4] != '\x00\x00'): - if _debug: - sys.stderr.write('stripping BOM\n') - if encoding != 'utf-16le': - sys.stderr.write('trying utf-16le instead\n') - encoding = 'utf-16le' - data = data[2:] - elif data[:3] == '\xef\xbb\xbf': - if _debug: - sys.stderr.write('stripping BOM\n') - if encoding != 'utf-8': - sys.stderr.write('trying utf-8 instead\n') - encoding = 'utf-8' - data = data[3:] - elif data[:4] == '\x00\x00\xfe\xff': - if _debug: - sys.stderr.write('stripping BOM\n') - if encoding != 'utf-32be': - sys.stderr.write('trying utf-32be instead\n') - encoding = 'utf-32be' - data = data[4:] - elif data[:4] == '\xff\xfe\x00\x00': - if _debug: - sys.stderr.write('stripping BOM\n') - if encoding != 'utf-32le': - sys.stderr.write('trying utf-32le instead\n') - encoding = 'utf-32le' - data = data[4:] - newdata = unicode(data, encoding) - if _debug: sys.stderr.write('successfully converted %s data to unicode\n' % encoding) - declmatch = re.compile('^<\?xml[^>]*?>') - newdecl = '''''' - if declmatch.search(newdata): - newdata = declmatch.sub(newdecl, newdata) - else: - newdata = newdecl + u'\n' + newdata - return newdata.encode('utf-8') - -def _stripDoctype(data): - '''Strips DOCTYPE from XML document, returns (rss_version, stripped_data) - - rss_version may be 'rss091n' or None - stripped_data is the same XML document, minus the DOCTYPE - ''' - entity_pattern = re.compile(r']*?)>', re.MULTILINE) - data = entity_pattern.sub('', data) - doctype_pattern = re.compile(r']*?)>', re.MULTILINE) - doctype_results = doctype_pattern.findall(data) - doctype = doctype_results and doctype_results[0] or '' - if doctype.lower().count('netscape'): - version = 'rss091n' - else: - version = None - data = doctype_pattern.sub('', data) - return version, data - -def parse(url_file_stream_or_string, etag=None, modified=None, agent=None, referrer=None, handlers=[]): - '''Parse a feed from a URL, file, stream, or string''' - result = FeedParserDict() - result['feed'] = FeedParserDict() - result['entries'] = [] - if _XML_AVAILABLE: - result['bozo'] = 0 - if type(handlers) == types.InstanceType: - handlers = [handlers] - try: - f = _open_resource(url_file_stream_or_string, etag, modified, agent, referrer, handlers) - data = f.read() - except Exception, e: - result['bozo'] = 1 - result['bozo_exception'] = e - data = '' - f = None - - # if feed is gzip-compressed, decompress it - if f and data and hasattr(f, 'headers'): - if gzip and f.headers.get('content-encoding', '') == 'gzip': - try: - data = gzip.GzipFile(fileobj=_StringIO(data)).read() - except Exception, e: - # Some feeds claim to be gzipped but they're not, so - # we get garbage. Ideally, we should re-request the - # feed without the 'Accept-encoding: gzip' header, - # but we don't. - result['bozo'] = 1 - result['bozo_exception'] = e - data = '' - elif zlib and f.headers.get('content-encoding', '') == 'deflate': - try: - data = zlib.decompress(data, -zlib.MAX_WBITS) - except Exception, e: - result['bozo'] = 1 - result['bozo_exception'] = e - data = '' - - # save HTTP headers - if hasattr(f, 'info'): - info = f.info() - result['etag'] = info.getheader('ETag') - last_modified = info.getheader('Last-Modified') - if last_modified: - result['modified'] = _parse_date(last_modified) - if hasattr(f, 'url'): - result['href'] = f.url - result['status'] = 200 - if hasattr(f, 'status'): - result['status'] = f.status - if hasattr(f, 'headers'): - result['headers'] = f.headers.dict - if hasattr(f, 'close'): - f.close() - - # there are four encodings to keep track of: - # - http_encoding is the encoding declared in the Content-Type HTTP header - # - xml_encoding is the encoding declared in the ; changed -# project name -#2.5 - 7/25/2003 - MAP - changed to Python license (all contributors agree); -# removed unnecessary urllib code -- urllib2 should always be available anyway; -# return actual url, status, and full HTTP headers (as result['url'], -# result['status'], and result['headers']) if parsing a remote feed over HTTP -- -# this should pass all the HTTP tests at ; -# added the latest namespace-of-the-week for RSS 2.0 -#2.5.1 - 7/26/2003 - RMK - clear opener.addheaders so we only send our custom -# User-Agent (otherwise urllib2 sends two, which confuses some servers) -#2.5.2 - 7/28/2003 - MAP - entity-decode inline xml properly; added support for -# inline and as used in some RSS 2.0 feeds -#2.5.3 - 8/6/2003 - TvdV - patch to track whether we're inside an image or -# textInput, and also to return the character encoding (if specified) -#2.6 - 1/1/2004 - MAP - dc:author support (MarekK); fixed bug tracking -# nested divs within content (JohnD); fixed missing sys import (JohanS); -# fixed regular expression to capture XML character encoding (Andrei); -# added support for Atom 0.3-style links; fixed bug with textInput tracking; -# added support for cloud (MartijnP); added support for multiple -# category/dc:subject (MartijnP); normalize content model: 'description' gets -# description (which can come from description, summary, or full content if no -# description), 'content' gets dict of base/language/type/value (which can come -# from content:encoded, xhtml:body, content, or fullitem); -# fixed bug matching arbitrary Userland namespaces; added xml:base and xml:lang -# tracking; fixed bug tracking unknown tags; fixed bug tracking content when -# element is not in default namespace (like Pocketsoap feed); -# resolve relative URLs in link, guid, docs, url, comments, wfw:comment, -# wfw:commentRSS; resolve relative URLs within embedded HTML markup in -# description, xhtml:body, content, content:encoded, title, subtitle, -# summary, info, tagline, and copyright; added support for pingback and -# trackback namespaces -#2.7 - 1/5/2004 - MAP - really added support for trackback and pingback -# namespaces, as opposed to 2.6 when I said I did but didn't really; -# sanitize HTML markup within some elements; added mxTidy support (if -# installed) to tidy HTML markup within some elements; fixed indentation -# bug in _parse_date (FazalM); use socket.setdefaulttimeout if available -# (FazalM); universal date parsing and normalization (FazalM): 'created', modified', -# 'issued' are parsed into 9-tuple date format and stored in 'created_parsed', -# 'modified_parsed', and 'issued_parsed'; 'date' is duplicated in 'modified' -# and vice-versa; 'date_parsed' is duplicated in 'modified_parsed' and vice-versa -#2.7.1 - 1/9/2004 - MAP - fixed bug handling " and '. fixed memory -# leak not closing url opener (JohnD); added dc:publisher support (MarekK); -# added admin:errorReportsTo support (MarekK); Python 2.1 dict support (MarekK) -#2.7.4 - 1/14/2004 - MAP - added workaround for improperly formed
        tags in -# encoded HTML (skadz); fixed unicode handling in normalize_attrs (ChrisL); -# fixed relative URI processing for guid (skadz); added ICBM support; added -# base64 support -#2.7.5 - 1/15/2004 - MAP - added workaround for malformed DOCTYPE (seen on many -# blogspot.com sites); added _debug variable -#2.7.6 - 1/16/2004 - MAP - fixed bug with StringIO importing -#3.0b3 - 1/23/2004 - MAP - parse entire feed with real XML parser (if available); -# added several new supported namespaces; fixed bug tracking naked markup in -# description; added support for enclosure; added support for source; re-added -# support for cloud which got dropped somehow; added support for expirationDate -#3.0b4 - 1/26/2004 - MAP - fixed xml:lang inheritance; fixed multiple bugs tracking -# xml:base URI, one for documents that don't define one explicitly and one for -# documents that define an outer and an inner xml:base that goes out of scope -# before the end of the document -#3.0b5 - 1/26/2004 - MAP - fixed bug parsing multiple links at feed level -#3.0b6 - 1/27/2004 - MAP - added feed type and version detection, result['version'] -# will be one of SUPPORTED_VERSIONS.keys() or empty string if unrecognized; -# added support for creativeCommons:license and cc:license; added support for -# full Atom content model in title, tagline, info, copyright, summary; fixed bug -# with gzip encoding (not always telling server we support it when we do) -#3.0b7 - 1/28/2004 - MAP - support Atom-style author element in author_detail -# (dictionary of 'name', 'url', 'email'); map author to author_detail if author -# contains name + email address -#3.0b8 - 1/28/2004 - MAP - added support for contributor -#3.0b9 - 1/29/2004 - MAP - fixed check for presence of dict function; added -# support for summary -#3.0b10 - 1/31/2004 - MAP - incorporated ISO-8601 date parsing routines from -# xml.util.iso8601 -#3.0b11 - 2/2/2004 - MAP - added 'rights' to list of elements that can contain -# dangerous markup; fiddled with decodeEntities (not right); liberalized -# date parsing even further -#3.0b12 - 2/6/2004 - MAP - fiddled with decodeEntities (still not right); -# added support to Atom 0.2 subtitle; added support for Atom content model -# in copyright; better sanitizing of dangerous HTML elements with end tags -# (script, frameset) -#3.0b13 - 2/8/2004 - MAP - better handling of empty HTML tags (br, hr, img, -# etc.) in embedded markup, in either HTML or XHTML form (
        ,
        ,
        ) -#3.0b14 - 2/8/2004 - MAP - fixed CDATA handling in non-wellformed feeds under -# Python 2.1 -#3.0b15 - 2/11/2004 - MAP - fixed bug resolving relative links in wfw:commentRSS; -# fixed bug capturing author and contributor URL; fixed bug resolving relative -# links in author and contributor URL; fixed bug resolvin relative links in -# generator URL; added support for recognizing RSS 1.0; passed Simon Fell's -# namespace tests, and included them permanently in the test suite with his -# permission; fixed namespace handling under Python 2.1 -#3.0b16 - 2/12/2004 - MAP - fixed support for RSS 0.90 (broken in b15) -#3.0b17 - 2/13/2004 - MAP - determine character encoding as per RFC 3023 -#3.0b18 - 2/17/2004 - MAP - always map description to summary_detail (Andrei); -# use libxml2 (if available) -#3.0b19 - 3/15/2004 - MAP - fixed bug exploding author information when author -# name was in parentheses; removed ultra-problematic mxTidy support; patch to -# workaround crash in PyXML/expat when encountering invalid entities -# (MarkMoraes); support for textinput/textInput -#3.0b20 - 4/7/2004 - MAP - added CDF support -#3.0b21 - 4/14/2004 - MAP - added Hot RSS support -#3.0b22 - 4/19/2004 - MAP - changed 'channel' to 'feed', 'item' to 'entries' in -# results dict; changed results dict to allow getting values with results.key -# as well as results[key]; work around embedded illformed HTML with half -# a DOCTYPE; work around malformed Content-Type header; if character encoding -# is wrong, try several common ones before falling back to regexes (if this -# works, bozo_exception is set to CharacterEncodingOverride); fixed character -# encoding issues in BaseHTMLProcessor by tracking encoding and converting -# from Unicode to raw strings before feeding data to sgmllib.SGMLParser; -# convert each value in results to Unicode (if possible), even if using -# regex-based parsing -#3.0b23 - 4/21/2004 - MAP - fixed UnicodeDecodeError for feeds that contain -# high-bit characters in attributes in embedded HTML in description (thanks -# Thijs van de Vossen); moved guid, date, and date_parsed to mapped keys in -# FeedParserDict; tweaked FeedParserDict.has_key to return True if asking -# about a mapped key -#3.0fc1 - 4/23/2004 - MAP - made results.entries[0].links[0] and -# results.entries[0].enclosures[0] into FeedParserDict; fixed typo that could -# cause the same encoding to be tried twice (even if it failed the first time); -# fixed DOCTYPE stripping when DOCTYPE contained entity declarations; -# better textinput and image tracking in illformed RSS 1.0 feeds -#3.0fc2 - 5/10/2004 - MAP - added and passed Sam's amp tests; added and passed -# my blink tag tests -#3.0fc3 - 6/18/2004 - MAP - fixed bug in _changeEncodingDeclaration that -# failed to parse utf-16 encoded feeds; made source into a FeedParserDict; -# duplicate admin:generatorAgent/@rdf:resource in generator_detail.url; -# added support for image; refactored parse() fallback logic to try other -# encodings if SAX parsing fails (previously it would only try other encodings -# if re-encoding failed); remove unichr madness in normalize_attrs now that -# we're properly tracking encoding in and out of BaseHTMLProcessor; set -# feed.language from root-level xml:lang; set entry.id from rdf:about; -# send Accept header -#3.0 - 6/21/2004 - MAP - don't try iso-8859-1 (can't distinguish between -# iso-8859-1 and windows-1252 anyway, and most incorrectly marked feeds are -# windows-1252); fixed regression that could cause the same encoding to be -# tried twice (even if it failed the first time) -#3.0.1 - 6/22/2004 - MAP - default to us-ascii for all text/* content types; -# recover from malformed content-type header parameter with no equals sign -# ('text/xml; charset:iso-8859-1') -#3.1 - 6/28/2004 - MAP - added and passed tests for converting HTML entities -# to Unicode equivalents in illformed feeds (aaronsw); added and -# passed tests for converting character entities to Unicode equivalents -# in illformed feeds (aaronsw); test for valid parsers when setting -# XML_AVAILABLE; make version and encoding available when server returns -# a 304; add handlers parameter to pass arbitrary urllib2 handlers (like -# digest auth or proxy support); add code to parse username/password -# out of url and send as basic authentication; expose downloading-related -# exceptions in bozo_exception (aaronsw); added __contains__ method to -# FeedParserDict (aaronsw); added publisher_detail (aaronsw) -#3.2 - 7/3/2004 - MAP - use cjkcodecs and iconv_codec if available; always -# convert feed to UTF-8 before passing to XML parser; completely revamped -# logic for determining character encoding and attempting XML parsing -# (much faster); increased default timeout to 20 seconds; test for presence -# of Location header on redirects; added tests for many alternate character -# encodings; support various EBCDIC encodings; support UTF-16BE and -# UTF16-LE with or without a BOM; support UTF-8 with a BOM; support -# UTF-32BE and UTF-32LE with or without a BOM; fixed crashing bug if no -# XML parsers are available; added support for 'Content-encoding: deflate'; -# send blank 'Accept-encoding: ' header if neither gzip nor zlib modules -# are available -#3.3 - 7/15/2004 - MAP - optimize EBCDIC to ASCII conversion; fix obscure -# problem tracking xml:base and xml:lang if element declares it, child -# doesn't, first grandchild redeclares it, and second grandchild doesn't; -# refactored date parsing; defined public registerDateHandler so callers -# can add support for additional date formats at runtime; added support -# for OnBlog, Nate, MSSQL, Greek, and Hungarian dates (ytrewq1); added -# zopeCompatibilityHack() which turns FeedParserDict into a regular -# dictionary, required for Zope compatibility, and also makes command- -# line debugging easier because pprint module formats real dictionaries -# better than dictionary-like objects; added NonXMLContentType exception, -# which is stored in bozo_exception when a feed is served with a non-XML -# media type such as 'text/plain'; respect Content-Language as default -# language if not xml:lang is present; cloud dict is now FeedParserDict; -# generator dict is now FeedParserDict; better tracking of xml:lang, -# including support for xml:lang='' to unset the current language; -# recognize RSS 1.0 feeds even when RSS 1.0 namespace is not the default -# namespace; don't overwrite final status on redirects (scenarios: -# redirecting to a URL that returns 304, redirecting to a URL that -# redirects to another URL with a different type of redirect); add -# support for HTTP 303 redirects -#4.0 - MAP - support for relative URIs in xml:base attribute; fixed -# encoding issue with mxTidy (phopkins); preliminary support for RFC 3229; -# support for Atom 1.0; support for iTunes extensions; new 'tags' for -# categories/keywords/etc. as array of dict -# {'term': term, 'scheme': scheme, 'label': label} to match Atom 1.0 -# terminology; parse RFC 822-style dates with no time; lots of other -# bug fixes -#4.1 - MAP - removed socket timeout; added support for chardet library diff --git a/plugins/FlexRSS/plugin.py b/plugins/FlexRSS/plugin.py deleted file mode 100644 index 4fd015a93..000000000 --- a/plugins/FlexRSS/plugin.py +++ /dev/null @@ -1,1734 +0,0 @@ -def gtk_treeview_search_cb_stristr(model, column, key, iter, data=None): - value = model.get_value(iter, column) - if value.lower().find(key.lower()) > -1: - return False - else: - return True - -class plugin_FlexRSS_Config: - constants = { - 'Generic' : 0, - 'TV Show' : 1, - 'TV Show (dated)' : 2 } - feeds_counter = 0 - filters_counter = 0 - feeds = None - filters = None - version = 0 - show_toolbar_button = False - threaded_retrieval = False - - def getFilter(self, id): - if not self.filters: - return None - - for filter in self.filters: - if filter['id'] == id: - return filter - - return None - - def setFilter(self, id, key, value): - filter = self.getFilter(id) - - if not filter: - return False - else: - filter[key] = value - return True - - def addFilter(self, name, type, patterns, feeds): - id = self.feeds_counter + 1 - self.feeds_counter = id - - if not self.filters: - self.filters = [] - - filter = { "id" : id, - "name" : name, - "type" : type, - "patterns" : patterns, - "feeds" : feeds, - "history" : {}, - "path" : None, - "enabled" : True, - "queue_top": False, - "pause" : False, - "delete" : False} - - self.filters.append(filter) - - return id - - def deleteFilter(self, id): - if not self.filters: - return False - - i = 0 - while i < len(self.filters): - if self.filters[i]['id'] == id: - del self.filters[i] - return True - i = i + 1 - - def checkHistory(self, id, type, data): - filter = self.getFilter(id) - - if not filter: - return False - - try: - if type == self.constants['TV Show']: - filter['history'][type][data['series']].index(data['episode']) - return True - elif type == self.constants['TV Show (dated)']: - filter['history'][type][data['year']][data['month']].index(data['day']) - return True - else: - filter['history'][type].index(data['url']) - return True - except: - return False - - def checkRange(self, id, type, data): - filter = self.getFilter(id) - - if not filter: - return False - - if type == self.constants['TV Show']: - if filter['history'][type].has_key('from'): - if data['series'] < filter['history'][type]['from']['season']: - return False - elif data['series'] == filter['history'][type]['from']['season']: - if data['episode'] < filter['history'][type]['from']['episode']: - return False - - if filter['history'][type].has_key('thru'): - if data['series'] > filter['history'][type]['thru']['season']: - return False - elif data['series'] == filter['history'][type]['thru']['season']: - if data['episode'] > filter['history'][type]['thru']['episode']: - return False - - return True - - elif type == self.constants['TV Show (dated)']: - if filter['history'][type].has_key('from'): - if data['year'] < filter['history'][type]['from']['year']: - return False - elif data['year'] == filter['history'][type]['from']['year']: - if data['month'] < filter['history'][type]['from']['month']: - return False - elif data['month'] == filter['history'][type]['from']['month']: - if data['day'] < filter['history'][type]['from']['day']: - return False - - if filter['history'][type].has_key('thru'): - if data['year'] > filter['history'][type]['thru']['year']: - return False - elif data['year'] == filter['history'][type]['thru']['year']: - if data['month'] > filter['history'][type]['thru']['month']: - return False - elif data['month'] == filter['history'][type]['thru']['month']: - if data['day'] > filter['history'][type]['thru']['day']: - return False - - return True - - else: - return True - - def addHistory(self, id, type, data): - filter = self.getFilter(id) - - if not filter: - return False - - if type == self.constants['TV Show']: - if not filter['history'].has_key(type): - filter['history'][type] = {} - if not filter['history'][type].has_key(data['series']): - filter['history'][type][data['series']] = [] - filter['history'][type][data['series']].append(data['episode']) - elif type == self.constants['TV Show (dated)']: - if not filter['history'].has_key(type): - filter['history'][type] = {} - if not filter['history'][type].has_key(data['year']): - filter['history'][type][data['year']] = {} - if not filter['history'][type][data['year']].has_key(data['month']): - filter['history'][type][data['year']][data['month']] = [] - filter['history'][type][data['year']][data['month']].append(data['day']) - else: - if not filter['history'].has_key(type): - filter['history'][type] = [] - try: - filter['history'][type].append(data['url']) - except AttributeError, e: - filter['history'][type] = [data['url']] - - def getFeed(self, id): - if not self.feeds: - return None - - for feed in self.feeds: - if feed['id'] == id: - return feed - - return None - - def setFeed(self, id, key, value): - feed = self.getFeed(id) - - if not feed: - return False - else: - feed[key] = value - return True - - def addFeed(self, name, url, interval): - # Uhhh... no ++? WTF is the increment operator? - id = self.feeds_counter + 1 - self.feeds_counter = id - - if not self.feeds: - self.feeds = [] - - self.feeds.append({ "id" : id, - "name" : name, - "url" : url, - "interval" : interval, - "enabled" : True }) - - return id - - def deleteFeed(self, id): - if not self.feeds: - return False - - i = 0 - while i < len(self.feeds): - if self.feeds[i]['id'] == id: - del self.feeds[i] - return True - i = i + 1 - -class plugin_FlexRSS: - config = None - glade = None - feeds = None - toolbar_button = None - history_calendarbuttons = None - - def update_config(self): - if self.config.version >= 5: - return - - if self.config.version < 1: - print 'Updating config to v1' - i = 0 - while i < len(self.config.filters): - self.config.filters[i]['enabled'] = True - i = i + 1 - - if self.config.version < 2: - print 'Updating config to v2' - i = 0 - while i < len(self.config.feeds): - self.config.feeds[i]['enabled'] = True - i = i + 1 - - if self.config.version < 3: - print 'Updating config to v3' - i = 0 - while i < len(self.config.filters): - type_s = self.config.filters[i]['type'] - type_i = self.config.constants[type_s] - if self.config.filters[i]['history'].has_key(type_s): - history = { type_i: self.config.filters[i]['history'][type_s] } - self.config.filters[i]['history'] = history - self.config.filters[i]['type'] = self.config.constants[self.config.filters[i]['type']]; - i = i + 1 - - if self.config.version < 4: - print 'Updating config to v4' - i = 0 - while i < len(self.config.filters): - self.config.filters[i]['queue_top'] = False - self.config.filters[i]['pause'] = False - i = i + 1 - - if self.config.version < 5: - print 'Updating config to v5' - i = 0 - while i < len(self.config.filters): - self.config.filters[i]['delete'] = False - i = i + 1 - - self.config.version = 5 - self.write_config() - - def load_config(self): - import deluge.common, os, cookielib - - file = deluge.common.CONFIG_DIR + "/flexrss.dat" - if os.path.isfile(file): - import pickle - - fd = open(file, 'r') - self.config = pickle.load(fd) - fd.close() - else: - self.config = plugin_FlexRSS_Config() - self.config.version = 5 - - self.update_config() - - cookie_file = deluge.common.CONFIG_DIR + "/flexrss-cookies.txt" - self.cookies = cookielib.MozillaCookieJar() - if os.path.isfile(cookie_file): - self.cookies.load(cookie_file) - - def write_config(self, write_cookies=False): - import deluge.common, os, pickle - - file = deluge.common.CONFIG_DIR + "/flexrss.dat" - fd = open(file, 'w') - pickle.dump(self.config, fd) - fd.close() - - if write_cookies: - print "Saving cookies." - self.cookies.save(deluge.common.CONFIG_DIR + "/flexrss-cookies.txt") - - def configure_cb_closed(self, args): - self.glade = None - self.history_calendarbuttons = None - - def configure_cb_feed_new(self, args): - feed = { "name" : 'Untitled', - "url" : 'http://', - "interval" : 900, - "id" : 0 } - - feed["id"] = self.config.addFeed(feed["name"], feed["url"], feed["interval"]) - - view = self.glade.get_widget("FlexRSS_Feeds") - model = view.get_model() - view.get_selection().select_iter(model.append(None, (feed["id"], feed["name"], feed["url"]))) - - def configure_cb_feed_selected(self, selection): - model, iter = selection.get_selected() - - if not iter: - return - - parent = model.iter_parent(iter) - if parent: # Selected a filter - self.glade.get_widget('FlexRSS_Filters_Test_Pattern').set_text(model.get_value(iter, 1)) - self.configure_cb_test_filter(None) - - iter = parent - - # We want to edit a feed. - feed = self.config.getFeed(model.get_value(iter, 0)) - if not feed: - print 'Error: could not find feed #' + str(model.get_value(iter, 0)) - return - - self.glade.get_widget("FlexRSS_EditFeed_Name").set_text(feed["name"]) - self.glade.get_widget("FlexRSS_EditFeed_URL").set_text(feed["url"]) - self.glade.get_widget("FlexRSS_EditFeed_Interval").set_text(str(feed["interval"])) - if feed["enabled"] == True: - self.glade.get_widget("FlexRSS_EditFeed_Status_Enabled").set_active(True) - else: - self.glade.get_widget("FlexRSS_EditFeed_Status_Disabled").set_active(True) - self.glade.get_widget('FlexRSS_Feeds_Editor').show() - - def configure_cb_feed_delete(self, arg, id=None): - if not id: - # Which feed is selected? - selection = self.glade.get_widget("FlexRSS_Feeds").get_selection() - model, iter = selection.get_selected() - - if not iter: - return - - id = model.get_value(iter, 0) - if id == 0: - id = model.get_value(model.iter_parent(iter), 0) - else: - model = self.glade.get_widget("FlexRSS_Feeds").get_model() - iter = model.get_iter_first() - while iter: - if model.get_value(iter, 0) == id: - break - iter = model.iter_next(iter) - - if not iter: - print 'Couldn\'t find feed.' - return - - # Remove from config - if not self.config.deleteFeed(id): - print 'Unable to delete feed #' + str(id) - return - - # Remove from UI - model.remove(iter) - - self.write_config() - - # We are no longer editing a feed, so hide the editing widgets. - self.glade.get_widget('FlexRSS_Feeds_Editor').hide() - - def configure_cb_feed_save(self, arg, id=None): - if not id: - # Which feed is selected? - selection = self.glade.get_widget("FlexRSS_Feeds").get_selection() - model, iter = selection.get_selected() - - if not iter: - return - - id = model.get_value(iter, 0) - if id == 0: - iter = model.iter_parent(iter) - id = model.get_value(iter, 0) - else: - model = self.glade.get_widget("FlexRSS_Feeds").get_model() - iter = model.iter_first() - while iter: - if model.get_value(iter, 0) == id: - break - iter = iter.iter_next(iter) - - if not iter: - print 'Couldn\'t find feed.' - return - - # Update configuration - self.config.setFeed(id, "name", self.glade.get_widget("FlexRSS_EditFeed_Name").get_text()) - self.config.setFeed(id, "url", self.glade.get_widget("FlexRSS_EditFeed_URL").get_text()) - interval = self.configure_ui_get_text_as_int("FlexRSS_EditFeed_Interval", 900) - if interval < 300: - # It's just not polite to hit a server that often. - self.glade.get_widget("FlexRSS_EditFeed_Interval").set_text('300') - interval = 300 - self.config.setFeed(id, "interval", interval) - self.config.setFeed(id, "enabled", self.glade.get_widget("FlexRSS_EditFeed_Status_Enabled").get_active()) - self.write_config() - - # Update UI - feed = self.config.getFeed(id) - model.set_value(iter, 0, feed["id"]) - model.set_value(iter, 1, feed["name"]) - model.set_value(iter, 2, feed["url"]) - - if not self.feeds.has_key(id): - self.feeds[id] = { 'cfg' : feed, - 'updated' : 0, - 'data' : [] } - - def escape_regex_special_chars(self, pattern): - escape_chars = '[]()^$\\.?*+|' - out = [] - for c in pattern: - try: - escape_chars.index(c) - out.append('\\' + c) - except: - out.append(c) - return ''.join(out) - - def configure_cb_filter_new(self, arg, test_pattern=None): - filter = { "name" : "Untitled", - "type" : "Generic", - "patterns" : [('', 'Title')], - "feeds" : [0], - "id" : 0 } - - if test_pattern: - # Try to guess a good pattern - import re, string - - trans_table = string.maketrans(' ', '.') - - # TV Show - exp = re.compile(r'(.*?)S([0-9]+)E([0-9]+)', re.IGNORECASE) - match = exp.match(test_pattern) - if match: - pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + 's%se%e' - filter['patterns'][0] = (pattern, 'Title') - filter['name'] = match.group(1) - filter['type'] = self.config.constants['TV Show'] - - if not match: - exp = re.compile(r'(.*?)([0-9]{4}).([0-9]{1,2}).([0-9]{1,2})', re.IGNORECASE) - match = exp.match(test_pattern) - if match: - pattern = None - if ((int(match.group(3)) <= 12) and (int(match.group(4)) <= 31)): - pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%Y.%m.%d' - elif ((int(match.group(3)) <= 31) and (int(match.group(4)) <= 12)): - pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%Y.%d.%m' - - if pattern: - filter['patterns'][0] = (pattern, 'Title') - filter['name'] = match.group(1) - filter['type'] = self.config.constants['TV Show (dated)'] - else: - match = None - - if not match: - exp = re.compile(r'(.*?)([0-9]{2}).([0-9]{2}).([0-9]{2})', re.IGNORECASE) - match = exp.match(test_pattern) - if match: - pattern = None - if ((int(match.group(2)) <= 12) and (int(match.group(3)) <= 31)): - pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%m.%d.%y' - elif ((int(match.group(3)) <= 31) and (int(match.group(2)) <= 12)): - pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%d.%m.%y' - - if pattern: - filter['patterns'][0] = (pattern, 'Title') - filter['name'] = match.group(1) - filter['type'] = self.config.constants['TV Show (dated)'] - else: - match = None - - if not match: - exp = re.compile(r'(.*?)([0-9]+)([x\.\-_]{1})([0-9]+)', re.IGNORECASE) - match = exp.match(test_pattern) - if match: - pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%s' + self.escape_regex_special_chars(match.group(3)) + '%e' - filter['patterns'][0] = (pattern, 'Title') - filter['name'] = match.group(1) - filter['type'] = self.config.constants['TV Show'] - - if not match: - exp = re.compile(r'(.*?)([0-9]+)$', re.IGNORECASE) - match = exp.match(test_pattern) - if match: - pattern = self.escape_regex_special_chars(match.group(1)).lower().translate(trans_table) + '%e' - filter['patterns'][0] = (pattern, 'Title') - filter['name'] = match.group(1) - filter['type'] = self.config.constants['TV Show'] - - # Add to config - filter['id'] = self.config.addFilter(filter['name'], filter['type'], filter['patterns'], [0]) - - # Add to UI - self.configure_ui_add_filter(self.config.getFilter(filter['id']), test_pattern) - - def configure_cb_filter_selected(self, selection): - model, iter = selection.get_selected() - - if not iter: - return - - # We want to edit a filter. - filter = self.config.getFilter(model.get_value(iter, 0)) - if not filter: - print 'Error: could not find filter #' + str(model.get_value(iter, 0)) - return - - self.configure_ui_reset_filter() - - self.glade.get_widget('FlexRSS_Filters_Name').set_text(filter['name']) - - if filter['type'] == self.config.constants['TV Show']: - type_i = 1 - elif filter['type'] == self.config.constants['TV Show (dated)']: - type_i = 2 - else: - type_i = 0 - - self.glade.get_widget('FlexRSS_Filters_Type').set_active(type_i) - - selection = self.glade.get_widget('FlexRSS_Filters_Feed').get_selection() - selection.unselect_all() - feed_model = self.glade.get_widget('FlexRSS_Filters_Feed').get_model() - for i in filter['feeds']: - if i == 0: - selection.select_all() - else: - iter = feed_model.get_iter_first() - while iter: - if feed_model.get_value(iter, 0) == i: - selection.select_iter(iter) - iter = feed_model.iter_next(iter) - - for pattern in filter['patterns']: - self.configure_ui_add_pattern(pattern) - - if filter['type'] == self.config.constants['TV Show']: - if filter['history'].has_key(filter['type']) and filter['history'][filter['type']].has_key('from'): - self.glade.get_widget('FlexRSS_History_TVShow_From_Enabled').set_active(True) - self.glade.get_widget('FlexRSS_History_TVShow_From_Season').set_sensitive(True) - self.glade.get_widget('FlexRSS_History_TVShow_From_Episode').set_sensitive(True) - self.glade.get_widget('FlexRSS_History_TVShow_From_Season').set_text(str(filter['history'][filter['type']]['from']['season'])) - self.glade.get_widget('FlexRSS_History_TVShow_From_Episode').set_text(str(filter['history'][filter['type']]['from']['episode'])) - else: - self.glade.get_widget('FlexRSS_History_TVShow_From_Enabled').set_active(False) - self.glade.get_widget('FlexRSS_History_TVShow_From_Season').set_sensitive(False) - self.glade.get_widget('FlexRSS_History_TVShow_From_Episode').set_sensitive(False) - self.glade.get_widget('FlexRSS_History_TVShow_From_Season').set_text('0') - self.glade.get_widget('FlexRSS_History_TVShow_From_Episode').set_text('0') - - if filter['history'].has_key(filter['type']) and filter['history'][filter['type']].has_key('thru'): - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Enabled').set_active(True) - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Season').set_sensitive(True) - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Episode').set_sensitive(True) - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Season').set_text(str(filter['history'][filter['type']]['thru']['season'])) - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Episode').set_text(str(filter['history'][filter['type']]['thru']['episode'])) - else: - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Enabled').set_active(False) - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Season').set_sensitive(False) - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Episode').set_sensitive(False) - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Season').set_text('0') - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Episode').set_text('0') - - self.glade.get_widget("FlexRSS_History_TVShow_Dated").hide() - self.glade.get_widget("FlexRSS_History_TVShow").show() - self.glade.get_widget("FlexRSS_Filter_History_Range").show() - elif filter['type'] == self.config.constants['TV Show (dated)']: - import time - - cal_from, cal_thru = self.history_calendarbuttons - today = time.localtime() - - if filter['history'].has_key(filter['type']) and filter['history'][filter['type']].has_key('from'): - self.glade.get_widget('FlexRSS_History_TVShow_Dated_From_Enabled').set_active(True) - cal_from.set_sensitive(True) - cal_from.set_date(filter['history'][filter['type']]['from']['year'], - filter['history'][filter['type']]['from']['month'], - filter['history'][filter['type']]['from']['day']) - else: - self.glade.get_widget('FlexRSS_History_TVShow_Dated_From_Enabled').set_active(False) - cal_from.set_sensitive(False) - cal_from.set_date(today[0], today[1], today[2]) - - if filter['history'].has_key(filter['type']) and filter['history'][filter['type']].has_key('thru'): - self.glade.get_widget('FlexRSS_History_TVShow_Dated_Thru_Enabled').set_active(True) - cal_thru.set_sensitive(True) - cal_thru.set_date(filter['history'][filter['type']]['thru']['year'], - filter['history'][filter['type']]['thru']['month'], - filter['history'][filter['type']]['thru']['day']) - else: - self.glade.get_widget('FlexRSS_History_TVShow_Dated_Thru_Enabled').set_active(False) - cal_thru.set_sensitive(False) - cal_thru.set_date(today[0], today[1], today[2]) - - self.glade.get_widget("FlexRSS_History_TVShow").hide() - self.glade.get_widget("FlexRSS_History_TVShow_Dated").show() - self.glade.get_widget("FlexRSS_Filter_History_Range").show() - else: - self.glade.get_widget("FlexRSS_History_TVShow").hide() - self.glade.get_widget("FlexRSS_History_TVShow_Dated").hide() - self.glade.get_widget("FlexRSS_Filter_History_Range").hide() - - self.glade.get_widget('FlexRSS_Filter_Download_QueueTop').set_active(filter.get('queue_top', False)) - self.glade.get_widget('FlexRSS_Filter_Download_Pause').set_active(filter.get('pause', False)) - self.glade.get_widget('FlexRSS_Filter_Download_Delete').set_active(filter.get('delete', False)) - - self.configure_cb_test_filter(None) - - if filter['path'] != None: - self.glade.get_widget('FlexRSS_Filter_Output_Location').set_current_folder(filter['path']) - self.glade.get_widget('FlexRSS_Filter_Output_Type_Custom').set_active(True) - else: - self.glade.get_widget('FlexRSS_Filter_Output_Type_Default').set_active(True) - - replace = filter.get('replace', {'pattern': '', 'with': ''}) - self.glade.get_widget('FlexRSS_Filter_Rewrite_Pattern').set_text(replace['pattern']) - self.glade.get_widget('FlexRSS_Filter_Rewrite_Replacement').set_text(replace['with']) - - def configure_cb_filter_history_toggle(self, box): - name = box.get_name() - active = box.get_active() - - if name == 'FlexRSS_History_TVShow_From_Enabled': - self.glade.get_widget('FlexRSS_History_TVShow_From_Season').set_sensitive(active) - self.glade.get_widget('FlexRSS_History_TVShow_From_Episode').set_sensitive(active) - elif name == 'FlexRSS_History_TVShow_Thru_Enabled': - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Season').set_sensitive(active) - self.glade.get_widget('FlexRSS_History_TVShow_Thru_Episode').set_sensitive(active) - elif name == 'FlexRSS_History_TVShow_Dated_From_Enabled': - self.history_calendarbuttons[0].set_sensitive(active) - elif name == 'FlexRSS_History_TVShow_Dated_Thru_Enabled': - self.history_calendarbuttons[1].set_sensitive(active) - - self.configure_cb_test_filter(None) - - def configure_ui_get_text_as_int(self, widget_name, default=0): - try: - return int(self.glade.get_widget(widget_name).get_text()) - except: - return default - - def configure_ui_get_history_restriction(self): - h_from = None - h_thru = None - - type = self.glade.get_widget('FlexRSS_Filters_Type').get_active() - if type == 1: - type_s = self.config.constants['TV Show'] - elif type == 2: - type_s = self.config.constants['TV Show (dated)'] - else: - type_s = self.config.constants['Generic'] - - if type_s == self.config.constants['TV Show']: - if self.glade.get_widget('FlexRSS_History_TVShow_From_Enabled').get_active(): - from_season = self.configure_ui_get_text_as_int('FlexRSS_History_TVShow_From_Season') - from_episode = self.configure_ui_get_text_as_int('FlexRSS_History_TVShow_From_Episode') - h_from = {'season': from_season, 'episode': from_episode} - elif type_s == self.config.constants['TV Show (dated)']: - if self.glade.get_widget('FlexRSS_History_TVShow_Dated_From_Enabled').get_active(): - from_y, from_m, from_d = self.history_calendarbuttons[0].get_date() - h_from = {'year': from_y, 'month': from_m, 'day': from_d} - - if type_s == self.config.constants['TV Show']: - if self.glade.get_widget('FlexRSS_History_TVShow_Thru_Enabled').get_active(): - thru_season = self.configure_ui_get_text_as_int('FlexRSS_History_TVShow_Thru_Season') - thru_episode = self.configure_ui_get_text_as_int('FlexRSS_History_TVShow_Thru_Episode') - h_thru = {'season': thru_season, 'episode': thru_episode} - elif type_s == self.config.constants['TV Show (dated)']: - if self.glade.get_widget('FlexRSS_History_TVShow_Dated_Thru_Enabled').get_active(): - thru_y, thru_m, thru_d = self.history_calendarbuttons[1].get_date() - h_thru = {'year': thru_y, 'month': thru_m, 'day': thru_d} - - return (h_from, h_thru) - - def configure_cb_filter_save(self, arg): - # Which feed is selected? - selection = self.glade.get_widget("FlexRSS_Filters_List").get_selection() - model, iter = selection.get_selected() - - if not iter: - return - - id = model.get_value(iter, 0) - name = self.glade.get_widget('FlexRSS_Filters_Name').get_text() - self.config.setFilter(id, 'name', name) - iter = model.get_iter_first() - while iter: - if model.get_value(iter, 0) == id: - model.set_value(iter, 1, name) - iter = model.iter_next(iter) - - type = self.glade.get_widget('FlexRSS_Filters_Type').get_active() - if type == 1: - type_s = self.config.constants['TV Show'] - elif type == 2: - type_s = self.config.constants['TV Show (dated)'] - else: - type_s = self.config.constants['Generic'] - self.config.setFilter(id, 'type', type_s) - - model, paths = self.glade.get_widget('FlexRSS_Filters_Feed').get_selection().get_selected_rows() - feeds = [] - for path in paths: - feeds.append(model.get_value(model.get_iter(path), 0)) - if len(feeds) == 0: - feeds.append(0) - self.config.setFilter(id, 'feeds', feeds) - - patterns = [] - filter_patterns = self.glade.get_widget('FlexRSS_Filter_Patterns_List') - for i in filter_patterns.get_children(): - data = i.get_children() - pattern = data[0].get_text() - if data[2].get_active() == 1: - type = 'Link' - else: - type = 'Title' - patterns.append((pattern, type)) - self.config.setFilter(id, 'patterns', patterns) - - if self.glade.get_widget('FlexRSS_Filter_Output_Type_Custom').get_active(): - path = self.glade.get_widget('FlexRSS_Filter_Output_Location').get_current_folder() - else: - path = None - - self.config.setFilter(id, 'path', path) - - self.config.setFilter(id, 'queue_top', self.glade.get_widget('FlexRSS_Filter_Download_QueueTop').get_active()) - self.config.setFilter(id, 'pause', self.glade.get_widget('FlexRSS_Filter_Download_Pause').get_active()) - self.config.setFilter(id, 'delete', self.glade.get_widget('FlexRSS_Filter_Download_Delete').get_active()) - - filter = self.config.getFilter(id) - - h_from, h_thru = self.configure_ui_get_history_restriction() - if filter['type'] != self.config.constants['Generic']: - if not filter['history'].has_key(filter['type']): - filter['history'][filter['type']] = {} - - if h_from != None: - filter['history'][filter['type']]['from'] = h_from - else: - if filter['history'][filter['type']].has_key('from'): - del filter['history'][filter['type']]['from'] - - if h_thru != None: - filter['history'][filter['type']]['thru'] = h_thru - else: - if filter['history'][filter['type']].has_key('thru'): - del filter['history'][filter['type']]['thru'] - - filter['replace'] = { 'pattern': self.glade.get_widget('FlexRSS_Filter_Rewrite_Pattern').get_text(), - 'with' : self.glade.get_widget('FlexRSS_Filter_Rewrite_Replacement').get_text() } - - self.write_config() - - def configure_cb_remove_pattern(self, arg): - arg.get_parent().destroy() - - def configure_ui_add_pattern(self, pattern): - import gtk, gobject - - filter_patterns = self.glade.get_widget('FlexRSS_Filter_Patterns_List') - - hbox = gtk.HBox() - filter_patterns.pack_start(hbox) - - input = gtk.Entry() - input.set_text(pattern[0]) - input.connect("changed", self.configure_cb_test_filter) - - on = gtk.Label() - on.set_text('On') - on.show() - - combo = gtk.combo_box_new_text() - combo.append_text('Title') - combo.append_text('Link') - if pattern[1] == 'Link': - combo.set_active(1) - else: - combo.set_active(0) - - remove = gtk.Button(stock=gtk.STOCK_REMOVE) - remove.connect("pressed", self.configure_cb_remove_pattern) - - hbox.pack_start(input) - hbox.pack_start(on, expand=False) - hbox.pack_start(combo, expand=False) - hbox.pack_start(remove, expand=False) - - hbox.show_all() - - def configure_cb_add_pattern(self, args): - self.configure_ui_add_pattern(('', 'Title')) - - def configure_ui_add_filter(self, filter, test_pattern=None): - if not filter: - print 'No filter to add' - return None - - self.configure_ui_reset_filter() - - model = self.glade.get_widget("FlexRSS_Filters_List").get_model() - iter = model.append((filter['id'], filter['name'], filter['enabled'])) - - if not iter: - return - - view = self.glade.get_widget("FlexRSS_Filters_List") - model = view.get_model() - view.get_selection().select_iter(iter) - - if test_pattern: - self.glade.get_widget('FlexRSS_Filters_Test_Pattern').set_text(test_pattern) - self.configure_cb_test_filter(None) - - self.glade.get_widget('FlexRSS_MainNotebook').set_current_page(1) - - def configure_ui_test_result(self, result, h_match=False): - if result and h_match: - self.glade.get_widget('FlexRSS_Filters_Test_Result').set_text('Match') - else: - self.glade.get_widget('FlexRSS_Filters_Test_Result').set_text('Doesn\'t match') - - type = self.glade.get_widget('FlexRSS_Filters_Type').get_active() - - if type == 0: # Generic - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow').hide() - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated').hide() - self.glade.get_widget('FlexRSS_History_TVShow').hide() - self.glade.get_widget('FlexRSS_History_TVShow_Dated').hide() - elif type == 1: # TV Show - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow').show() - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated').hide() - self.glade.get_widget('FlexRSS_History_TVShow').show() - self.glade.get_widget('FlexRSS_History_TVShow_Dated').hide() - if result: - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Series').set_text(str(result['series'])) - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Episode').set_text(str(result['episode'])) - else: - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Series').set_text('0') - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Episode').set_text('0') - else: # TV Show (dated) - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow').hide() - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated').show() - self.glade.get_widget('FlexRSS_History_TVShow').hide() - self.glade.get_widget('FlexRSS_History_TVShow_Dated').show() - if result: - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Year').set_text(str(result['year'])) - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Month').set_text(str(result['month'])) - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Day').set_text(str(result['day'])) - else: - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Year').set_text('0') - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Month').set_text('0') - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated_Day').set_text('0') - - def configure_cb_test_filter(self, source=None, date=None): - subject = self.glade.get_widget('FlexRSS_Filters_Test_Pattern').get_text() - - type = self.glade.get_widget('FlexRSS_Filters_Type').get_active() - if type == 1: - type_s = self.config.constants['TV Show'] - elif type == 2: - type_s = self.config.constants['TV Show (dated)'] - else: - type_s = self.config.constants['Generic'] - - filter_patterns = self.glade.get_widget('FlexRSS_Filter_Patterns_List') - for i in filter_patterns.get_children(): - data = i.get_children() - pattern = data[0].get_text() - result = self.test_pattern(type_s, subject, pattern) - if result: - # Pattern matched, let's try history restriction. - h_from, h_thru = self.configure_ui_get_history_restriction() - h_match = self.test_range(type_s, result, h_from, h_thru) - self.configure_ui_test_result(result, h_match) - return - - self.configure_ui_test_result(False) - - def configure_cb_delete_filter(self, arg): - # Which filter is selected? - selection = self.glade.get_widget("FlexRSS_Filters_List").get_selection() - model, iter = selection.get_selected() - - if not iter: - return - - id = model.get_value(iter, 0) - - # Remove from config - if not self.config.deleteFilter(id): - print 'Unable to delete filter #' + str(id) - return - self.write_config() - - # Remove from UI - model.remove(iter) - - self.configure_ui_reset_filter() - - def configure_cb_feed_refresh(self, caller, id=None): - if not id: - selection = self.glade.get_widget("FlexRSS_Feeds").get_selection() - model, iter = selection.get_selected() - - if not iter: - return - - id = model.get_value(iter, 0) - - if id: - if ( self.config.threaded_retrieval ): - import threading - threading.Thread(target=self.parse_feed, args=(id,)).start() - else: - self.parse_feed(id) - - def configure_cb_download_torrent(self, caller, url): - self.download_torrent(url) - - def configure_cb_feed_popup(self, view, event): - if event.button != 3: - return - - model = view.get_model() - coords = event.get_coords() - path = view.get_path_at_pos(int(coords[0]), int(coords[1])) - if path: - iter = model.get_iter(path[0]) - else: - iter = None - - import gtk - - popup = gtk.Menu() - - if iter: - id = model.get_value(iter, 0) - if id: # Feed - item_refresh = gtk.MenuItem(_("Refresh feed")) - item_refresh.connect("activate", self.configure_cb_feed_refresh, id) - popup.append(item_refresh) - - item_delete = gtk.MenuItem(_("Delete feed")) - item_delete.connect("activate", self.configure_cb_feed_delete, id) - popup.append(item_delete) - - else: # Filter - item_filter = gtk.MenuItem(_("Create filter")) - item_filter.connect("activate", self.configure_cb_filter_new, model.get_value(iter, 1)) - popup.append(item_filter) - - item_download = gtk.MenuItem(_("Download torrent")) - item_download.connect("activate", self.configure_cb_download_torrent, model.get_value(iter, 2)) - popup.append(item_download) - - else: # Neither - item_new = gtk.MenuItem("New feed") - item_new.connect("activate", self.configure_cb_feed_new) - popup.append(item_new) - - popup.popup(None, None, None, event.button, event.time) - popup.show_all() - - def configure_cb_output_set(self, chooser): - self.glade.get_widget('FlexRSS_Filter_Output_Type_Custom').set_active(True) - - def configure_ui_reset_filter(self): - # Just resets the crap in the filter tab to defaults. - self.glade.get_widget('FlexRSS_Filters_Name').set_text('') - self.glade.get_widget('FlexRSS_Filters_Type').set_active(0) - self.glade.get_widget('FlexRSS_Filters_Feed').get_selection().unselect_all() - for filter in self.glade.get_widget('FlexRSS_Filter_Patterns_List').get_children(): - filter.destroy() - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow').hide() - self.glade.get_widget('FlexRSS_Filters_Test_Results_TVShow_Dated').hide() - file_chooser = self.glade.get_widget('FlexRSS_Filter_Output_Location') - file_chooser.set_current_folder(self.interface.config.get('default_download_path')) - self.glade.get_widget('FlexRSS_Filter_Output_Type_Default').set_active(True) - - def strcasecmp(self, s1, s2): - try: - t1 = s1.lower() - t2 = s2.lower() - - if s1 < s2: - return -1 - elif s1 > s2: - return 1 - except: - pass - - return 0 - - def configure_ui_sort_cmp(self, model, iter1, iter2, user_data=None): - if (model.get_value(iter1, 0) == 0) or (model.get_value(iter2, 0) == 0): - return 0 - - return self.strcasecmp(model.get_value(iter1, 1), model.get_value(iter2, 1)) - - def configure_cb_filter_toggled(self, renderer, path): - old_val = renderer.get_active() - model = self.glade.get_widget('FlexRSS_Filters_List').get_model() - iter = model.get_iter(path) - if old_val: - model.set_value(iter, 2, False) - self.config.setFilter(model.get_value(iter, 0), 'enabled', False) - else: - model.set_value(iter, 2, True) - self.config.setFilter(model.get_value(iter, 0), 'enabled', True) - self.write_config() - - def configure_cb_cookie_new(self, src): - self.configure_ui_cookie_reset() - self.glade.get_widget("FlexRSS_Cookies_Editor").show() - - def configure_cb_cookie_save(self, src): - import cookielib, time - - domain = self.glade.get_widget("FlexRSS_Cookie_Domain").get_text() - path = self.glade.get_widget("FlexRSS_Cookie_Path").get_text() - name = self.glade.get_widget("FlexRSS_Cookie_Name").get_text() - value = self.glade.get_widget("FlexRSS_Cookie_Value").get_text() - - if (domain == ""): - return - - if path == '': - path = '/' - - # Fragile. - self.cookies._policy._now = self.cookies._now = int(time.time()) - cookie = self.cookies._cookie_from_cookie_tuple((name, value, {"domain": domain, "path":path, "expires":2147483647}, {}), None) - - self.cookies.set_cookie(cookie) - self.configure_ui_add_cookie(None, cookie) - self.configure_ui_cookie_reset() - self.glade.get_widget("FlexRSS_Cookies_Editor").hide() - self.write_config(True) - - def configure_ui_add_cookie(self, model, cookie): - if cookie.domain[0] == '.': - domain = cookie.domain[1:] - else: - domain = cookie.domain - - if model == None: - model = self.glade.get_widget("FlexRSS_Cookies_List").get_model() - - parent = None - iter = model.get_iter_first() - while iter: - t = model.get_value(iter, 0) - if t == domain: - parent = iter - break - iter = model.iter_next(iter) - - if parent == None: - parent = model.append(iter, (domain, "", "", "")) - model.append(parent, (cookie.domain, cookie.path, cookie.name, cookie.value)) - - def configure_ui_cookie_reset(self): - self.glade.get_widget("FlexRSS_Cookie_Domain").set_text('') - self.glade.get_widget("FlexRSS_Cookie_Path").set_text('/') - self.glade.get_widget("FlexRSS_Cookie_Name").set_text('') - self.glade.get_widget("FlexRSS_Cookie_Value").set_text('') - - def configure_cb_cookie_selected(self, selection): - model, iter = selection.get_selected() - - self.configure_ui_cookie_reset() - self.glade.get_widget("FlexRSS_Cookies_Editor").hide() - - def configure_cb_cookie_delete(self, src): - selection = self.glade.get_widget("FlexRSS_Cookies_List").get_selection() - model, iter = selection.get_selected() - - domain = None - path = None - name = None - - if not model.iter_has_child(iter): - path = model.get_value(iter, 1) - name = model.get_value(iter, 2) - domain = model.get_value(iter, 0) - - try: - self.cookies.clear("." + domain, path, name) - except: - pass - try: - self.cookies.clear(domain, path, name) - except: - pass - - # UI - if model.iter_has_child(iter): - i = model.iter_children(iter) - while model.remove(i): - pass - model.remove(iter) - else: - p = model.iter_parent(iter) - model.remove(iter) - if not model.iter_has_child(p): - model.remove(p) - - self.write_config(True) - - def configure_cb_toolbar_clicked(self, button): - self.configure() - - def configure_ui_show_toolbar_button(self): - if self.toolbar_button == None: - import gtk - import os.path - - icon = gtk.Image() - icon.set_from_file(os.path.join(self.path, "FlexRSS.png")) - self.toolbar_button = gtk.ToolButton(icon_widget=icon, label="FlexRSS") - self.toolbar_button.connect("clicked", self.configure_cb_toolbar_clicked) - self.interface.toolbar.add(self.toolbar_button) - self.toolbar_button.show_all() - - def configure_cb_toolbar_toggled(self, box): - if box.get_active(): - self.configure_ui_show_toolbar_button() - self.config.show_toolbar_button = True - self.write_config() - else: - self.toolbar_button.destroy() - self.toolbar_button = None - self.config.show_toolbar_button = False - self.write_config() - - def configure_cb_threaded_toggled(self, box): - self.config.threaded_retrieval = box.get_active() - self.write_config() - - def configure(self, widget=None): - if self.glade: # Dialog already running - return - - import gtk, gtk.glade, gobject - - self.glade = gtk.glade.XML(self.path + "/FlexRSS.glade") - - # Intialize feed lists - feeds_model = gtk.TreeStore(gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_STRING) - feeds_view = self.glade.get_widget("FlexRSS_Feeds") - filters_feeds_view = self.glade.get_widget("FlexRSS_Filters_Feed") - feeds_view.set_model(feeds_model) - filters_feeds_view.set_model(feeds_model) - feeds_model.set_sort_func(1, self.configure_ui_sort_cmp) - feeds_model.set_sort_column_id(1, gtk.SORT_ASCENDING) - - # Setup columns for feeds tab - renderer_name = gtk.CellRendererText() - column_name = gtk.TreeViewColumn(_("Feed Name"), renderer_name, text=1) - feeds_view.append_column(column_name) - renderer_url = gtk.CellRendererText() - column_url = gtk.TreeViewColumn(_("URL"), renderer_url, text=2) - feeds_view.append_column(column_url) - feeds_view.set_search_column(1) - feeds_view.set_search_equal_func(gtk_treeview_search_cb_stristr) - - # Set callback for when selection is changed in feeds tab - # I can't figure out how to do this in Glade - feeds_view.get_selection().connect("changed", self.configure_cb_feed_selected) - - # Setup columns for feed list on filters tab - renderer_name = gtk.CellRendererText() - column_name = gtk.TreeViewColumn(_("Feed Name"), renderer_name, text=1) - filters_feeds_view.append_column(column_name) - - # Allow multiple selections of feeds in filters tab - # I can't figure out how to do this in Glade - filters_feeds_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE) - - # Populate feed lists - if self.config.feeds: - for feed in self.config.feeds: - this_feed = feeds_model.append(None, (feed['id'], feed['name'], feed['url'])) - for item in self.feeds[feed['id']]['data']: - feeds_model.append(this_feed, (0, item['title'], item['link'])) - - - # Initialize filters list - filters_model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN) - filters_view = self.glade.get_widget("FlexRSS_Filters_List") - filters_view.set_model(filters_model) - feeds_model.set_sort_func(1, self.configure_ui_sort_cmp) - filters_model.set_sort_column_id(1, gtk.SORT_ASCENDING) - - # Setup columns for filters list - renderer_enabled = gtk.CellRendererToggle() - column_enabled = gtk.TreeViewColumn(_("Enabled"), renderer_enabled, active=2) - filters_view.append_column(column_enabled) - renderer_enabled.connect('toggled', self.configure_cb_filter_toggled) - renderer_name = gtk.CellRendererText() - column_name = gtk.TreeViewColumn(_("Filter Name"), renderer_name, text=1) - filters_view.append_column(column_name) - - # Set callback for when selection is changed in feeds tab - # I can't figure out how to do this in Glade - filters_view.get_selection().connect("changed", self.configure_cb_filter_selected) - - # Populate filters list - if self.config.filters: - for filter in self.config.filters: - filters_model.append((filter['id'], filter['name'], filter['enabled'])) - - # Filter types - filter_types = self.glade.get_widget('FlexRSS_Filters_Type') - filter_types.append_text(_("Generic")) - filter_types.append_text(_("TV Show")) - filter_types.append_text(_("TV Show (dated)")) - - # Calendar buttons for dated tv show history restrictions - from CalendarButton import CalendarButton - dated_from = CalendarButton() - dated_from.connect('date-selected', self.configure_cb_test_filter) - dated_to = CalendarButton() - dated_to.connect('date-selected', self.configure_cb_test_filter) - dated_from.show() - dated_to.show() - history_table = self.glade.get_widget('FlexRSS_History_TVShow_Dated') - history_table.attach(dated_from, 1, 2, 0, 1, gtk.EXPAND|gtk.FILL, gtk.FILL) - history_table.attach(dated_to, 1, 2, 1, 2, gtk.EXPAND|gtk.FILL, gtk.FILL) - self.history_calendarbuttons = (dated_from, dated_to) - - # Initialize cookies list - cookies_model = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) - cookies_view = self.glade.get_widget("FlexRSS_Cookies_List") - cookies_view.set_model(cookies_model) - cookies_view.get_selection().connect("changed", self.configure_cb_cookie_selected) - - # Setup column for cookies - domain_renderer = gtk.CellRendererText() - domain_column = gtk.TreeViewColumn(_("Domain"), domain_renderer, text=0) - path_renderer = gtk.CellRendererText() - path_column = gtk.TreeViewColumn(_("Path"), path_renderer, text=1) - name_renderer = gtk.CellRendererText() - name_column = gtk.TreeViewColumn(_("Name"), name_renderer, text=2) - value_renderer = gtk.CellRendererText() - value_column = gtk.TreeViewColumn(_("Value"), value_renderer, text=3) - cookies_view.append_column(domain_column) - cookies_view.append_column(path_column) - cookies_view.append_column(name_column) - cookies_view.append_column(value_column) - - for cookie in self.cookies: - self.configure_ui_add_cookie(cookies_model, cookie) - - # Interface - self.glade.get_widget("FlexRSS_Interface_ShowButton").set_active(self.config.show_toolbar_button) - self.glade.get_widget("FlexRSS_Retrieval_Threaded").set_active(self.config.threaded_retrieval) - - # Callbacks for UI events - actions = { - # Feeds tab - "on_FlexRSS_MainWindow_destroy" : self.configure_cb_closed, - "on_FlexRSS_Feeds_New_pressed" : self.configure_cb_feed_new, - "on_FlexRSS_Feeds_Save_pressed" : self.configure_cb_feed_save, - "on_FlexRSS_Feeds_Delete_pressed" : self.configure_cb_feed_delete, - "on_FlexRSS_Feeds_button_press_event" : self.configure_cb_feed_popup, - - # Filters tab - "on_FlexRSS_Filters_Add_pressed" : self.configure_cb_filter_new, - "on_FlexRSS_Action_Save_pressed" : self.configure_cb_filter_save, - "on_FlexRSS_Filter_Patern_Add_pressed" : self.configure_cb_add_pattern, - "on_FlexRSS_Filters_Type_changed" : self.configure_cb_test_filter, - "on_FlexRSS_Filters_Test_Pattern" : self.configure_cb_test_filter, - "on_FlexRSS_Filters_Delete_pressed" : self.configure_cb_delete_filter, - "on_FlexRSS_History_TVShow_From_Enabled_toggled" : self.configure_cb_filter_history_toggle, - "on_FlexRSS_History_TVShow_Thru_Enabled_toggled" : self.configure_cb_filter_history_toggle, - "on_FlexRSS_History_TVShow_Dated_From_Enabled_toggled" : self.configure_cb_filter_history_toggle, - "on_FlexRSS_History_TVShow_Dated_Thru_Enabled_toggled" : self.configure_cb_filter_history_toggle, - "on_FlexRSS_History_TVShow_From_Season_changed" : self.configure_cb_test_filter, - "on_FlexRSS_History_TVShow_From_Episode_changed" : self.configure_cb_test_filter, - "on_FlexRSS_History_TVShow_Thru_Season_changed" : self.configure_cb_test_filter, - "on_FlexRSS_History_TVShow_Thru_Episode_changed" : self.configure_cb_test_filter, - - # Configuration tab - "on_FlexRSS_Cookie_New_pressed" : self.configure_cb_cookie_new, - "on_FlexRSS_Cookie_Save_pressed" : self.configure_cb_cookie_save, - "on_FlexRSS_Cookie_Delete_pressed" : self.configure_cb_cookie_delete, - "on_FlexRSS_Interface_ShowButton_toggled" : self.configure_cb_toolbar_toggled, - "on_FlexRSS_Retrieval_Threaded_toggled" : self.configure_cb_threaded_toggled } - if hasattr(self.interface, 'interactive_add_torrent_path'): - actions["on_FlexRSS_Filter_Output_Location_current_folder_changed"] = self.configure_cb_output_set - else: - self.glade.get_widget('FlexRSS_Filter_Output').hide() - self.glade.signal_autoconnect(actions) - - self.glade.get_widget("FlexRSS_MainWindow").show() - - def cmp_history(a, b): - try: - if a.has_key('series'): - if a['series'] > b['series']: - return 1 - elif a['series'] < b['series']: - return -1 - else: - if a['episode'] > b['episode']: - return 1 - elif a['episode'] < b['episode']: - return -1 - else: - return 0 - except: - return 0 - - def strptime2regex(self, input): - # Does'n exactly live up to its name yet. Currently just - # replaces %y,%Y,%m,%d with named patterns. In the future, it - # would be nice to allow escaping (e.g., %%Y means literal %Y) - # and expand it to support other formats. - patterns = [('%Y', '(?P[0-9]{4})'), - ('%y', '(?P[0-9]{2})'), - ('%m', '(?P[0-9]{1,2})'), - ('%d', '(?P[0-9]{1,2})')] - - out = input - for p in patterns: - out = out.replace(p[0], p[1]) - - return out - - def replace_tv_show_patterns(self, input): - patterns = [('%s', '(?P[0-9]+)'), - ('%e', '(?P[0-9]+)')] - - out = input - for p in patterns: - out = out.replace(p[0], p[1]) - - return out - - def test_range(self, type, data, h_from=None, h_thru=None): - if type == self.config.constants['TV Show']: - if h_from != None: - if data['series'] < h_from['season']: - return False - elif data['series'] == h_from['season']: - if data['episode'] < h_from['episode']: - return False - - if h_thru != None: - if data['series'] > h_thru['season']: - return False - elif data['series'] == h_thru['season']: - if data['episode'] > h_thru['episode']: - return False - - return True - - elif type == self.config.constants['TV Show (dated)']: - if h_from != None: - if data['year'] < h_from['year']: - return False - elif data['year'] == h_from['year']: - if data['month'] < h_from['month']: - return False - elif data['month'] == h_from['month']: - if data['day'] < h_from['day']: - return False - - if h_thru != None: - if data['year'] < h_thru['year']: - return False - elif data['year'] == h_thru['year']: - if data['month'] < h_thru['month']: - return False - elif data['month'] == h_thru['month']: - if data['day'] < h_thru['day']: - return False - - return True - - else: - return True - - def test_pattern(self, type, subject, pattern): - import re, time - result = False - - if len(pattern) < 1: - return False - - if type == self.config.constants['TV Show (dated)']: - pattern = self.strptime2regex(pattern) - elif type == self.config.constants['TV Show']: - pattern = self.replace_tv_show_patterns(pattern) - - # Wow, so this is lame... - if pattern[0] != '^': - pattern = '.*' + pattern - - try: - exp = re.compile(pattern, re.IGNORECASE) - except: - print 'Broken expression: ' + pattern - return False - - match = exp.match(subject) - if match: -# print 'Match: ' + subject -# print ' ' + pattern - if type == self.config.constants['TV Show']: - try: - series = int(match.group('s')) - except: - series = 0 - - try: - episode = int(match.group('e')) - except: - episode = 0 - - result = { 'series' : series, - 'episode' : episode } - - elif type == self.config.constants['TV Show (dated)']: - try: - year = int(match.group('Y')) - except: - try: - year = int(match.group('y')) - if year > 70: - year += 1900 - else: - year += 2000 - except: - year = 0 - - try: - month = int(match.group('m')) - except: - month = 0 - - try: - day = int(match.group('d')) - except: - day = 0 - - result = { 'year' : year, - 'month' : month, - 'day' : day } - - else: - result = True - - return result - - def make_opener(self): - import urllib2 - - return urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookies)) - - def make_request(self, location, referer=None): - import urllib2, deluge.common - - req = urllib2.Request(location) - req.add_header("User-Agent", "FlexRSS/%d.%d.%d (%s/%s)" % (self.version[0], self.version[1], self.version[2], deluge.common.PROGRAM_NAME, deluge.common.PROGRAM_VERSION)) - if referer != None: - req.add_header('Referer', referer) - - return req - - def open_url(self, location): - return self.make_opener().open(self.make_request(location)) - - def download_torrent(self, location, path=None, queue_top=False, pause=False, referer=None): - import tempfile, os, deluge.core - - try: - fd = self.open_url(location) - except: - return False - - inf = fd.info() - if inf["content-type"] != "application/x-bittorrent": - print "Warning: torrent content-type not application/x-bittorrent" - - (tmpfd, filename) = tempfile.mkstemp(".torrent", "flexrss-") - tfd = os.fdopen(tmpfd, 'wb') - tfd.write(fd.read()) - fd.close() - tfd.close() - - unique_id = False - - try: - if path is None: - path = self.interface.config.get('default_download_path') - unique_id = self.interface.manager.add_torrent(filename, path, self.interface.config.get('use_compact_storage')) - self.interface.torrent_model_append(unique_id) - - if queue_top == True: - try: - self.interface.manager.queue_top(unique_id) - except: - pass - if pause == True: - try: - self.interface.manager.set_user_pause(unique_id, True) - except: - pass - except deluge.core.DuplicateTorrentError, e: - print 'FlexRSS: torrent already exists.' - return True - except: - print '*** FlexRSS error: unable to add torrent.' - return False - - return True - - def parse_feed(self, id): - import time, feedparser, urllib2, cookielib - - feed = self.config.getFeed(id) - - #print 'Parsing feed: ' + feed['url'] - try: - parsed = feedparser.parse(self.open_url(feed['url'])) - if (not parsed) or (not parsed.entries): - print 'Unable to parse feed: ' + feed['url'] - return - except: - print 'Unable to update feed: ' + feed['url'] - return - #print 'Retrieval successful: ' + feed['url'] - - data = [] - - for entry in parsed.entries: - entryTitle = entry['title'] - - try: - entryLink = entry.links[0]['href'] - except: - try: - entryLink = entry.enclosures[0]['href'] - except: - print "Skipping %s\n" % entryTitle - continue - - try: - data.append({ 'title': entryTitle, 'link': entryLink }) - except: - continue - - if self.config.filters: - for filter in self.config.filters: - try: - if not ((feed['id'] in filter['feeds']) or (0 in filter['feeds'])): - continue - except TypeError: - filter['feeds'] = [0] - - if filter['enabled'] != True: - continue - - for pattern in filter['patterns']: - # (setq python-indent 4 - # tab-width 4) - # Okay, I dislike python substantially less now. - # Edit (~a month later): I still dislike it a lot, though. - try: - if pattern[1] == 'Title': - subject = entryTitle - else: - subject = entryLink - except: - print 'Unable to find subject.' - - match = self.test_pattern(filter['type'], subject, pattern[0]) - if match: - # Filter matched. Check history to see if - # we should download it. - if filter['type'] == self.config.constants['Generic']: # Dirty hack. - match = { 'url' : entryLink } - - torrent_url = entryLink - replace = filter.get('replace', {'pattern': '', 'with': ''}) - if len(replace['pattern']) > 0: - try: - import re - - p = re.compile(replace['pattern'], re.IGNORECASE) - torrent_url = p.sub(replace['with'], torrent_url) - except: - print '*** FlexRSS error: s/%s/%s/i failed.' % (replace['pattern'], replace['with']) - return - - if not self.config.checkHistory(filter['id'], filter['type'], match): - print filter - if filter.has_key('history'): - res = False - - if filter['type'] == self.config.constants['Generic']: - if filter['history'].get(filter['type'], []).count(torrent_url) == 0: - res = self.download_torrent(torrent_url, filter.get('path', None), filter['queue_top'], filter['pause'], feed['url']) - else: - h_from = filter['history'][filter['type']].get('from', None) - h_thru = filter['history'][filter['type']].get('thru', None) - if self.test_range(filter['type'], match, h_from, h_thru): - res = self.download_torrent(torrent_url, filter.get('path', None), filter['queue_top'], filter['pause'], feed['url']) - - print res - if res == True: - if filter['delete'] == True: - self.config.deleteFilter(filter['id']) - self.write_config() - - model = self.glade.get_widget("FlexRSS_Filters_List").get_model() - iter = model.get_iter_first(); - while iter != None: - if model.get_value(iter, 0) == filter['id']: - model.remove(iter) - break - iter = model.iter_next(iter) - else: - self.config.addHistory(filter['id'], filter['type'], match) - self.write_config() - - self.feeds[feed['id']]['data'] = data - if self.glade: # Update config window... - feeds_model = self.glade.get_widget("FlexRSS_Feeds").get_model() - iter = feeds_model.get_iter_first() - while iter != None: - if id == feeds_model.get_value(iter, 0): - break - iter = feeds_model.iter_next(iter) - - i = feeds_model.iter_children(iter) - if i != None: - while feeds_model.remove(i): - pass - - for item in data: - feeds_model.append(iter, (0, item['title'], item['link'])) - - def update(self): - import time, threading - - current_time = time.time() - - # I feel dirty for this. Oh, how I miss C. - for id in self.feeds: - if self.feeds[id]['cfg']['enabled'] == True: - if (current_time - self.feeds[id]['cfg']['interval']) > self.feeds[id]['updated']: - self.feeds[id]['updated'] = current_time - if ( self.config.threaded_retrieval ): - threading.Thread(target=self.parse_feed, args=(self.feeds[id]['cfg']['id'],)).start() - else: - self.parse_feed(self.feeds[id]['cfg']['id']) - - def unload(self): - if self.toolbar_button: - self.toolbar_button.destroy() - self.toolbar_button = None - - def deluge_version_compare(self, version): - import deluge.common - va = deluge.common.PROGRAM_VERSION.split('.') - dv = int(va[0]) * 1000000 - dv = dv + (int(va[1]) * 10000) - dv = dv + (int(va[2]) * 100) - if len(va) >= 4: - dv = dv + int(va[3]) - - if dv < version: - return -1 - elif dv > version: - return 1 - else: - return 0 - - def __init__(self, path, core, interface, defaults): - print "Found FlexRSS plugin..." - self.path = path - self.core = core - self.interface = interface - self.version = defaults['VERSION'] - - self.load_config() - - if self.config.show_toolbar_button == True: - self.configure_ui_show_toolbar_button() - - self.feeds = {} - if self.config.feeds: - for feed in self.config.feeds: - self.feeds[feed['id']] = { 'cfg' : feed, - 'updated' : 0, - 'data' : [] } - - # Debugging - # self.configure() diff --git a/plugins/MoveTorrent/__init__.py b/plugins/MoveTorrent/__init__.py deleted file mode 100644 index 2fc505926..000000000 --- a/plugins/MoveTorrent/__init__.py +++ /dev/null @@ -1,145 +0,0 @@ -# Copyright (C) 2007 - Marcos Pinto -# -# 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 2, 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 St, Fifth Floor, Boston, MA 02110-1301 USA. - -### Initialization ### - -plugin_name = "Move Torrent" -plugin_author = "Marcos Pinto" -plugin_version = "0.2" -plugin_description = _("This plugin allows users to move the torrent to a \ -different directory without having to remove and re-add the torrent. This \ -feature can be found by right-clicking on a torrent.\nFurthermore, it \ -allows the user to automatically have finished torrents moved to a different \ -folder.") - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return movetorrentMenu(path, core, interface) - - -import deluge -from deluge import dialogs -import gtk -import os.path - -DEFAULT_PREFS = { - "default_finished_path": os.path.expanduser("~"), - "enable_move_completed": False -} - -class movetorrentMenu: - - def __init__(self, path, core, interface): - print "Found MoveTorrent plugin..." - self.path = path - self.core = core - self.interface = interface - self.window = self.interface.window - self.dialogs = deluge.dialogs - self.core.connect_event(self.core.constants['EVENT_STORAGE_MOVED'], self.handle_event) - self.core.connect_event(self.core.constants['EVENT_FINISHED'], self.handle_event) - self.glade = gtk.glade.XML(os.path.join(path, "movetorrent.glade")) - self.glade.signal_autoconnect({ - 'dialog_ok': self.dialog_ok, - 'dialog_cancel': self.dialog_cancel - }) - self.dialog = self.glade.get_widget("dialog") - self.dialog.set_position(gtk.WIN_POS_CENTER) - - self.config_file = os.path.join(deluge.common.CONFIG_DIR, "move_torrent.conf") - self.config = deluge.pref.Preferences(self.config_file, global_defaults=False, defaults=DEFAULT_PREFS) - try: - self.config.load() - except IOError: - pass - - self.moveitem_image = gtk.Image() - self.moveitem_image.set_from_stock(gtk.STOCK_SAVE_AS, gtk.ICON_SIZE_MENU) - self.moveitem = gtk.ImageMenuItem(_("_Move Torrent")) - self.moveitem.set_image(self.moveitem_image) - self.moveitem.connect("activate", self.movetorrent_clicked) - self.interface.torrent_menu.append(self.moveitem) - self.moveitem.show_all() - self.switchitem_image = gtk.Image() - self.switchitem_image.set_from_stock(gtk.STOCK_CONVERT, gtk.ICON_SIZE_MENU) - self.switchitem = gtk.ImageMenuItem(_("_Switch Torrent Source")) - self.switchitem.set_image(self.switchitem_image) - self.switchitem.connect("activate", self.switchtorrent_clicked) - self.interface.torrent_menu.append(self.switchitem) - self.switchitem.show_all() - - def update(self): - pass - - def unload(self): - self.interface.torrent_menu.remove(self.moveitem) - self.interface.torrent_menu.remove(self.switchitem) - self.core.disconnect_event(self.core.constants['EVENT_STORAGE_MOVED'], self.handle_event) - self.core.disconnect_event(self.core.constants['EVENT_FINISHED'], self.handle_event) - self.config.save(self.config_file) - - def movetorrent_clicked(self, widget): - unique_ids = self.interface.get_selected_torrent_rows() - - path = self.dialogs.show_directory_chooser_dialog(None, \ - _("Choose a directory to move files to")) - if path: - self.paused_or_not = {} - for unique_id in unique_ids: - self.core.move_storage(unique_id, path) - - def switchtorrent_clicked(self, widget): - self.interface.torrent_switch_recheck(switch=True) - - def configure(self, window): - try: - self.glade.get_widget("chk_move_completed").set_active(self.config.get("enable_move_completed")) - self.glade.get_widget("finished_path_button").set_filename(self.config.get("default_finished_path")) - - except: - self.glade.get_widget("chk_move_completed").set_active(False) - self.glade.get_widget("default_finished_path").set_active(False) - self.dialog.set_transient_for(window) - self.dialog.show() - - def dialog_ok(self, source): - self.dialog.hide() - self.config.set("enable_move_completed", self.glade.get_widget("chk_move_completed").get_active()) - self.config.set("default_finished_path", self.glade.get_widget("finished_path_button").get_filename()) - - def dialog_cancel(self, source): - self.dialog.hide() - - def handle_event(self, event): - if event['event_type'] is self.core.constants['EVENT_STORAGE_MOVED']: - if event['message'] == self.core.unique_IDs[event['unique_ID']].save_dir: - self.dialogs.show_popup_warning(self.window, "An error occured while trying to move the torrent. Please check your permissions and note that you cannot move a torrent's files to the same directory that they are already stored or move a torrent's files before any of its files have actually been created.") - self.core.unique_IDs[event['unique_ID']].save_dir = event['message'] - self.core.pickle_state() - - elif event['event_type'] is self.core.constants['EVENT_FINISHED']: - if event['message'] == "torrent has finished downloading": - if self.config.get('enable_move_completed') and \ - self.config.get('default_finished_path') != \ - self.core.get_pref('default_download_path') and \ - self.core.unique_IDs[event['unique_ID']].save_dir != \ - self.config.get('default_finished_path'): - self.core.move_storage(event['unique_ID'], - self.config.get('default_finished_path')) diff --git a/plugins/NetworkGraph/__init__.py b/plugins/NetworkGraph/__init__.py deleted file mode 100644 index 5f999315b..000000000 --- a/plugins/NetworkGraph/__init__.py +++ /dev/null @@ -1,340 +0,0 @@ -# -*- coding: utf-8 -*- -# -# __init__.py -# -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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. - -plugin_name = "Network Activity Graph" -plugin_author = "Alon Zakai, Zach Tibbitts, Cinar Sahin" -plugin_version = "0.2.1" -plugin_description = _("Network Activity Graph plugin\n\nWritten by Kripkenstein") - - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return NetworkGraph(path, core, interface) - -from NetworkGraph.tab_graph import GraphTabManager - -import gtk -import deluge -import os.path - -class NetworkGraph: - def __init__(self, path, core, interface): - print "Found NetworkGraph plugin..." - self.parent = interface - self.location = path - self.manager = core - self.dialog_initialize = True - self.glade = gtk.glade.XML(os.path.join(path, "graph_preferences.glade")) - self.dialog = self.glade.get_widget("dialog") - self.glade.signal_autoconnect({ - 'on_Reset_Download_released' : self.reset_download, - 'on_Reset_Upload_released' : self.reset_upload, - 'on_button_cancel_pressed': self.cancel_pressed, - 'on_button_ok_pressed': self.ok_pressed - }) - - self.config_file = os.path.join(deluge.common.CONFIG_DIR, "graph.conf") - self.config = deluge.pref.Preferences(self.config_file, False) - try: - self.config.load() - except IOError: - # File does not exist - pass - - scrolledWindow = gtk.ScrolledWindow() - scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - image = gtk.Image() - - viewport = gtk.Viewport() - viewport.add(image) - scrolledWindow.add(viewport) - - image.show() - viewport.show() - self.topWidget = scrolledWindow - - self.parentNotebook = self.parent.notebook -# print "Parent NOTEBOOK:", self.parentNotebook - self.parentNotebook.append_page(self.topWidget, gtk.Label(_("Graph"))) -# print "My INDEX in parentNoteBook:", self.index - self.bootupRuns = 3 # This ensures that we pass the resizing phase, with scrollbars, etc. - # So the first time it is viewed, we are all ready - scrolledWindow.show() - import pango - pangoContext = self.parent.window.get_pango_context() - pangoLayout = pango.Layout(pangoContext) - - self.tab_graph = GraphTabManager(scrolledWindow, image, pangoLayout, self.manager) - self.update_config() - - def unload(self): # Shutdown is called when the plugin is deactivated - numPages = self.parentNotebook.get_n_pages() - for page in range(numPages): - if self.parentNotebook.get_nth_page(page) == self.topWidget: - self.parentNotebook.remove_page(page) - break - self.config.save(self.config_file) - - def configure(self, window): - self.dialog_initialize = True - try: - if self.config.get("enable_down_line"): - self.glade.get_widget("Download_Line_Check").set_active(True) - else: - self.glade.get_widget("Download_Line_Check").set_active(False) - - if self.config.get("enable_down_fill"): - self.glade.get_widget("Download_Fill_Check").set_active(True) - else: - self.glade.get_widget("Download_Fill_Check").set_active(False) - - if self.config.get("enable_up_line"): - self.glade.get_widget("Upload_Line_Check").set_active(True) - else: - self.glade.get_widget("Upload_Line_Check").set_active(False) - - if self.config.get("enable_up_fill"): - self.glade.get_widget("Upload_Fill_Check").set_active(True) - else: - self.glade.get_widget("Upload_Fill_Check").set_active(False) - - if (self.config.get("line_size") > 0) & (self.config.get("line_size") < 6): - self.glade.get_widget("Line_Scale").get_adjustment().set_value(self.config.get("line_size")) - else: - self.glade.get_widget("Line_Scale").get_adjustment().set_value(2); - - if (self.config.get("length") > 59) & (self.config.get("length") < 3601): - self.glade.get_widget("History_Scale").get_adjustment().set_value(self.config.get("length")) - else: - self.glade_get_widget("History_Scale").get_adjustment().set_value(60); - - if self.config.get("colors_set"): - dl_color = self.config.get("down_line_color") - df_color = self.config.get("down_fill_color") - ul_color = self.config.get("up_line_color") - uf_color = self.config.get("up_fill_color") - self.glade.get_widget("Download_Line").set_color(gtk.gdk.Color(int(dl_color[0]*65535),int(dl_color[1]*65535),int(dl_color[2]*65535))) - self.glade.get_widget("Download_Line").set_alpha(int(dl_color[3]*65535)) - self.glade.get_widget("Download_Fill").set_color(gtk.gdk.Color(int(df_color[0]*65535),int(df_color[1]*65535),int(df_color[2]*65535))) - self.glade.get_widget("Download_Fill").set_alpha(int(df_color[3]*65535)) - self.glade.get_widget("Upload_Line").set_color(gtk.gdk.Color(int(ul_color[0]*65535),int(ul_color[1]*65535),int(ul_color[2]*65535))) - self.glade.get_widget("Upload_Line").set_alpha(int(ul_color[3]*65535)) - self.glade.get_widget("Upload_Fill").set_color(gtk.gdk.Color(int(uf_color[0]*65535),int(uf_color[1]*65535),int(uf_color[2]*65535))) - self.glade.get_widget("Upload_Fill").set_alpha(int(uf_color[3]*65535)) - else: - self.glade.get_widget("Download_Line").set_color(gtk.gdk.Color(0,49151,0)) - self.glade.get_widget("Download_Line").set_alpha(65535) - self.glade.get_widget("Download_Fill").set_color(gtk.gdk.Color(32768,65535,32768)) - self.glade.get_widget("Download_Fill").set_alpha(65535) - self.glade.get_widget("Upload_Line").set_color(gtk.gdk.Color(0,0,65535)) - self.glade.get_widget("Upload_Line").set_alpha(49151) - self.glade.get_widget("Upload_Fill").set_color(gtk.gdk.Color(21627,21627,65535)) - self.glade.get_widget("Upload_Fill").set_alpha(32768) - - self.glade.get_widget("Mean_Speed_Check").set_active(self.config.get("mean_selected")) - self.glade.get_widget("Max_Speed_Check").set_active(self.config.get("max_selected")) - self.glade.get_widget("Legend_Check").set_active(self.config.get("legend_selected")) - - except: - self.glade.get_widget("Download_Line_Check").set_active(True) - self.glade.get_widget("Download_Fill_Check").set_active(True) - self.glade.get_widget("Upload_Line_Check").set_active(True) - self.glade.get_widget("Upload_Fill_Check").set_active(True) - self.glade.get_widget("Mean_Speed_Check").set_active(True) - self.glade.get_widget("Max_Speed_Check").set_active(True) - self.glade.get_widget("Download_Line").set_color(gtk.gdk.Color(0,49151,0)) - self.glade.get_widget("Download_Line").set_alpha(65535) - self.glade.get_widget("Download_Fill").set_color(gtk.gdk.Color(32768,65535,32768)) - self.glade.get_widget("Download_Fill").set_alpha(65535) - self.glade.get_widget("Upload_Line").set_color(gtk.gdk.Color(0,0,65535)) - self.glade.get_widget("Upload_Line").set_alpha(49151) - self.glade.get_widget("Upload_Fill").set_color(gtk.gdk.Color(21627,21627,65535)) - self.glade.get_widget("Upload_Fill").set_alpha(32768) - self.glade.get_widget("Line_Scale").get_adjustment().set_value(4); - self.glade.get_widget("History_Scale").get_adjustment().set_value(60); - self.glade.get_widget("Mean_Speed_Check").set_active(True) - self.glade.get_widget("Max_Speed_Check").set_active(False) - self.glade.get_widget("Legend_Check").set_active(True) - - self.dialog_initialize = False - self.dialog.set_transient_for(window) - self.dialog.show() - - def update(self): - if (not self.parentNotebook.get_nth_page(self.parentNotebook.get_current_page()) == \ - self.topWidget\ - or not self.parent.update_interface)\ - and not self.bootupRuns > 0: - self.tab_graph.update_graph_store() - self.bootupRuns = max(self.bootupRuns - 1, 0) - self.tab_graph.update_graph_store() - self.tab_graph.update_graph_view() - - def update_config(self): - if self.config.get("exists"): - if self.config.get("enable_down_line"): - self.tab_graph.enable_download_line() - else: - self.tab_graph.disable_download_line() - - if self.config.get("enable_down_fill"): - self.tab_graph.enable_download_fill() - else: - self.tab_graph.disable_download_fill() - - if self.config.get("enable_up_line"): - self.tab_graph.enable_upload_line() - else: - self.tab_graph.disable_upload_line() - - if self.config.get("enable_up_fill"): - self.tab_graph.enable_upload_fill() - else: - self.tab_graph.disable_upload_fill() - - - if self.config.get("down_line_color"): - self.tab_graph.download_line_color = self.config.get("down_line_color") - else: - self.tab_graph.download_line_color = (0, 0.75,0, 1.0) - - if self.config.get("down_fill_color"): - self.tab_graph.download_fill_color = self.config.get("down_fill_color") - else: - self.tab_graph.download_fill_color = (0.5,1, 0.5, 1.0) - - if self.config.get("up_line_color"): - self.tab_graph.upload_line_color = self.config.get("up_line_color") - else: - self.tab_graph.upload_line_color = (0, 0, 1.0, 0.75) - - if self.config.get("up_fill_color"): - self.tab_graph.upload_fill_color = self.config.get("up_fill_color") - else: - self.tab_graph.upload_fill_color = (0.33,0.33,1.0, 0.5) - - - if (self.config.get("line_size") > 0) & (self.config.get("line_size") < 6): - self.tab_graph.line_size = self.config.get("line_size") - else: - self.tab_graph.line_size = 4 - - if (self.config.get("length") > 59) & (self.config.get("length") < 3601): - self.tab_graph.length = self.config.get("length") - else: - self.tab_graph.length = 60 - - if self.config.get("mean_selected"): - self.tab_graph.enable_mean() - else: - self.tab_graph.disable_mean() - - if self.config.get("max_selected"): - self.tab_graph.enable_max() - else: - self.tab_graph.disable_max() - - if self.config.get("legend_selected"): - self.tab_graph.enable_legend() - else: - self.tab_graph.disable_legend() - else: - self.tab_graph.enable_download_line() - self.tab_graph.enable_download_fill() - self.tab_graph.enable_upload_line() - self.tab_graph.enable_upload_fill() - self.tab_graph.download_line_color = (0, 0.75,0, 1.0) - self.tab_graph.download_fill_color = (0.5,1, 0.5, 1.0) - self.tab_graph.upload_line_color = (0, 0, 1.0, 0.75) - self.tab_graph.upload_fill_color = (0.33,0.33,1.0, 0.5) - self.tab_graph.enable_mean() - self.tab_graph.enable_legend() - self.tab_graph.line_size = 4 - self.tab_graph.length = 60 - - def reset_download(self,src): - self.glade.get_widget("Download_Line_Check").set_active(True) - self.glade.get_widget("Download_Fill_Check").set_active(True) - self.glade.get_widget("Download_Line").set_color(gtk.gdk.Color(0,49151,0)) - self.glade.get_widget("Download_Line").set_alpha(65535) - self.glade.get_widget("Download_Fill").set_color(gtk.gdk.Color(32768,65535,32768)) - self.glade.get_widget("Download_Line").set_,sralpha(65535) - - def reset_upload(self,src): - self.glade.get_widget("Upload_Line_Check").set_active(True) - self.glade.get_widget("Upload_Fill_Check").set_active(True) - self.glade.get_widget("Upload_Line").set_color(gtk.gdk.Color(0,0,65535)) - self.glade.get_widget("Upload_Line").set_alpha(49151) - self.glade.get_widget("Upload_Fill").set_color(gtk.gdk.Color(21627,21627,65535)) - self.glade.get_widget("Upload_Fill").set_alpha(32768) - - def ok_pressed(self, src): - self.dialog.hide() - self.config.set("exists",True) - self.config.set("enable_down_line",self.glade.get_widget("Download_Line_Check").get_active()) - self.config.set("down_line_color",(self.glade.get_widget("Download_Line").get_color().red/65535.0,\ - self.glade.get_widget("Download_Line").get_color().green/65535.0,\ - self.glade.get_widget("Download_Line").get_color().blue/65535.0,\ - self.glade.get_widget("Download_Line").get_alpha()/65535.0)) - - self.config.set("enable_down_fill",self.glade.get_widget("Download_Fill_Check").get_active()) - self.config.set("down_fill_color",(self.glade.get_widget("Download_Fill").get_color().red/65535.0,\ - self.glade.get_widget("Download_Fill").get_color().green/65535.0,\ - self.glade.get_widget("Download_Fill").get_color().blue/65535.0,\ - self.glade.get_widget("Download_Fill").get_alpha()/65535.0)) - - self.config.set("enable_up_line",self.glade.get_widget("Upload_Line_Check").get_active()) - self.config.set("up_line_color",(self.glade.get_widget("Upload_Line").get_color().red/65535.0,\ - self.glade.get_widget("Upload_Line").get_color().green/65535.0,\ - self.glade.get_widget("Upload_Line").get_color().blue/65535.0,\ - self.glade.get_widget("Upload_Line").get_alpha()/65535.0)) - - self.config.set("enable_up_fill",self.glade.get_widget("Upload_Fill_Check").get_active()) - self.config.set("up_fill_color",(self.glade.get_widget("Upload_Fill").get_color().red/65535.0,\ - self.glade.get_widget("Upload_Fill").get_color().green/65535.0,\ - self.glade.get_widget("Upload_Fill").get_color().blue/65535.0,\ - self.glade.get_widget("Upload_Fill").get_alpha()/65535.0)) - - self.config.set("colors_set",True) - self.config.set("line_size",self.glade.get_widget("Line_Scale").get_adjustment().get_value()) - self.config.set("length",self.glade.get_widget("History_Scale").get_adjustment().get_value()) - self.config.set("mean_selected",self.glade.get_widget("Mean_Speed_Check").get_active()) - self.config.set("max_selected",self.glade.get_widget("Max_Speed_Check").get_active()) - self.config.set("legend_selected",self.glade.get_widget("Legend_Check").get_active()) - self.update_config() - - def cancel_pressed(self, src): - self.dialog.hide() diff --git a/plugins/NetworkGraph/graph_preferences.glade b/plugins/NetworkGraph/graph_preferences.glade deleted file mode 100644 index 5032fe8f7..000000000 --- a/plugins/NetworkGraph/graph_preferences.glade +++ /dev/null @@ -1,472 +0,0 @@ - - - - - - 5 - Network Activity Graph Preferences - GTK_WIN_POS_CENTER_ON_PARENT - GDK_WINDOW_TYPE_HINT_DIALOG - False - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - - 10 - 7 - 4 - - - True - True - Show Legend - 0 - True - - - 7 - 9 - 10 - GTK_FILL - GTK_FILL - - - - - True - True - True - Reset colors to their defaults - 0 - - - - True - gtk-clear - - - - - 6 - 7 - 3 - 4 - - - - - - - True - True - Show Max Speed - 0 - True - - - 7 - 7 - 8 - GTK_FILL - GTK_FILL - - - - - True - 0 - 1 - <b>Download</b> - True - - - 7 - GTK_FILL - GTK_FILL - - - - - True - True - Line - 0 - True - - - 1 - 2 - - GTK_FILL - - - - - 30 - True - - 0 - 1 - <b>Upload</b> - True - - - 7 - 2 - 3 - GTK_FILL - GTK_FILL - - - - - True - True - True - 0 - True - #0000c0c00000 - - - 1 - 2 - 1 - 2 - - - - - - - True - True - Fill - 1 - 0 - True - - - 3 - 4 - 1 - 2 - - GTK_FILL - - - - - True - True - True - 0 - True - #8080ffff8080 - - - 4 - 5 - 1 - 2 - - - - - - - True - True - Line - 0 - True - - - 3 - 4 - - GTK_FILL - - - - - True - True - True - 0 - True - #00000000ffff - 49153 - - - 1 - 2 - 3 - 4 - - - - - - - True - True - Fill - 0 - True - - - 3 - 4 - 3 - 4 - - GTK_FILL - - - - - True - True - True - 0 - True - #54545454ffff - 32768 - - - 4 - 5 - 3 - 4 - - - - - - - True - True - Show Mean Speed - 0 - True - - - 7 - 8 - 9 - GTK_FILL - GTK_FILL - - - - - 30 - True - 0 - 1 - <b>Misc</b> - True - PANGO_ELLIPSIZE_START - - - 7 - 4 - 5 - GTK_FILL - GTK_FILL - - - - - True - 60 60 3600 60 60 0 - 0 - GTK_POS_RIGHT - - - 2 - 7 - 5 - 6 - GTK_FILL - - - - - - True - History (sec) - - - 2 - 5 - 6 - - GTK_FILL - - - - - True - 4 1 5 0 0 0 - 0 - GTK_POS_RIGHT - - - 2 - 7 - 6 - 7 - GTK_FILL - - - - - - True - Line Size - - - 2 - 6 - 7 - - GTK_FILL - - - - - 20 - True - - - - 2 - 3 - 1 - 2 - GTK_FILL - GTK_FILL - 10 - - - - - 20 - True - - - - 2 - 3 - 3 - 4 - GTK_FILL - GTK_FILL - 10 - - - - - True - True - True - Reset colors to their defaults - 1 - 0 - - - - True - gtk-clear - - - - - 6 - 7 - 1 - 2 - - - - - - - 20 - True - - - - 5 - 6 - 1 - 2 - GTK_FILL - GTK_FILL - 10 - - - - - 20 - True - - - - 5 - 6 - 3 - 4 - GTK_FILL - GTK_FILL - 10 - - - - - False - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - GTK_BUTTONBOX_END - - - True - gtk-cancel - True - 0 - - - - - - True - gtk-ok - True - 1 - - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/plugins/NetworkGraph/tab_graph.py b/plugins/NetworkGraph/tab_graph.py deleted file mode 100644 index 0f2c97f64..000000000 --- a/plugins/NetworkGraph/tab_graph.py +++ /dev/null @@ -1,270 +0,0 @@ -# -*- coding: utf-8 -*- -# -# tab_graph.py -# -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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. - -import gtk -import pango -import cairo -import math -import deluge.common - -class GraphTabManager: - def __init__(self, scrolledWindow, image, pangoLayout, manager): - self.scrolledWindow = scrolledWindow - self.image = image - self.pangoLayout = pangoLayout - self.manager = manager - self.length = 60 - - self.width = -1 - self.height = -1 - - self.savedUpSpeeds = [] - self.savedDownSpeeds = [] - - self.download_line = None - self.download_line_color = None - self.download_fill = None - self.download_fill_color = None - self.upload_line = None - self.upload_line_color = None - self.upload_fill = None - self.upload_fill_color = None - self.max_selected = None - self.mean_selected = None - self.legend_selected = None - self.line_size = 4 - - #Download - def enable_download_line(self): - self.download_line = True - - def disable_download_line(self): - self.download_line = False - - def enable_download_fill(self): - self.download_fill = True - - def disable_download_fill(self): - self.download_fill = False - - #Upload - def enable_upload_line(self): - self.upload_line = True - - def disable_upload_line(self): - self.upload_line = False - - def enable_upload_fill(self): - self.upload_fill = True - - def disable_upload_fill(self): - self.upload_fill = False - - #Mean - def enable_mean(self): - self.mean_selected = True - - def disable_mean(self): - self.mean_selected = False - - #Max - def enable_max(self): - self.max_selected = True - - def disable_max(self): - self.max_selected = False - - #Legend - def enable_legend(self): - self.legend_selected = True - - def disable_legend(self): - self.legend_selected = False - - - def update_graph_store(self): - session_info = self.manager.get_state() - self.savedUpSpeeds.insert(0, session_info['upload_rate']) - if len(self.savedUpSpeeds) > self.length: - self.savedUpSpeeds.pop() - self.savedDownSpeeds.insert(0, session_info['download_rate']) - if len(self.savedDownSpeeds) > self.length: - self.savedDownSpeeds.pop() - - def update_graph_view(self): - extraWidth = self.scrolledWindow.get_vscrollbar().get_allocation().width * 1.5 - extraHeight = self.scrolledWindow.get_hscrollbar().get_allocation().height * 1.5 - allocation = self.scrolledWindow.get_allocation() - allocation.width = int(allocation.width) - extraWidth - allocation.height = int(allocation.height) - extraHeight - # Don't try to allocate a size too small, or you might crash - if allocation.width < 2 or allocation.height < 2: - return - -# savedDownSpeeds = [1,2,3,2,1] -# savedUpSpeeds = [5,8,0,0,1,2] - -# allocation = self.image.get_allocation() -# allocation.width = 300 -# allocation.height = 200 - - if not allocation.width == self.width or not allocation.height == self.height: -# print "New Pixmap!" - self.width = allocation.width - self.height = allocation.height - - self.networkPixmap = gtk.gdk.Pixmap(None, self.width,self.height,gtk.gdk.visual_get_system().depth) - self.image.set_from_pixmap(self.networkPixmap, None) - self.ctx = self.networkPixmap.cairo_create() - - self.networkPixmap.draw_rectangle(self.image.get_style().white_gc,True, 0, 0, self.width, self.height) - - if (self.download_fill or self.download_line) and (self.upload_fill or self.upload_line): - maxSpeed = max(max(self.savedDownSpeeds),max(self.savedUpSpeeds)) - meanSpeed = max(sum(self.savedUpSpeeds) /len(self.savedUpSpeeds), sum(self.savedDownSpeeds)/len(self.savedDownSpeeds)) - elif self.download_fill or self.download_line: - maxSpeed = max(self.savedDownSpeeds) - meanSpeed = sum(self.savedDownSpeeds)/len(self.savedDownSpeeds) - elif self.upload_fill or self.upload_line: - maxSpeed = max(self.savedUpSpeeds) - meanSpeed = sum(self.savedUpSpeeds) /len(self.savedUpSpeeds) - else: - maxSpeed = 0 - - if self.legend_selected: - self.drawLegend() - - if maxSpeed > 0: - if self.download_fill: - self.drawSpeedPoly(self.savedDownSpeeds,self.download_fill_color, maxSpeed, True) - - if self.download_line: - self.drawSpeedPoly(self.savedDownSpeeds,self.download_line_color,maxSpeed, False) - - if self.upload_fill: - self.drawSpeedPoly(self.savedUpSpeeds,self.upload_fill_color,maxSpeed, True) - - if self.upload_line: - self.drawSpeedPoly(self.savedUpSpeeds,self.upload_line_color,maxSpeed, False) - - if self.max_selected: - self.drawText(deluge.common.fspeed(maxSpeed),self.image.get_style().black_gc,4,2) - - if self.mean_selected: - self.pangoLayout.set_text(deluge.common.fspeed(meanSpeed)) - self.networkPixmap.draw_layout(self.image.get_style().black_gc, - 4, - int(self.height - 1 - ((self.height-28)*meanSpeed/maxSpeed)), - self.pangoLayout) - self.networkPixmap.draw_line(self.image.get_style().black_gc, - 0, - int(self.height - ((self.height-28)*meanSpeed/maxSpeed)), - self.width, - int(self.height - ((self.height-28)*meanSpeed/maxSpeed))) - - self.networkPixmap.draw_rectangle(self.image.get_style().black_gc,False, 0, 0, self.width-1, self.height-1) - self.image.queue_draw() - - def tracePath(self, speeds, maxSpeed): - lineWidth = self.line_size - - self.ctx.set_line_width(lineWidth) - self.ctx.move_to(self.width + lineWidth,self.height + lineWidth) - self.ctx.line_to(self.width + lineWidth,int(self.height-((self.height-28)*speeds[0]/maxSpeed))) - - for i in range(len(speeds)): - self.ctx.line_to(int(self.width-1-((i*self.width)/(self.length-1))),int(self.height-1-((self.height-28)*speeds[i]/maxSpeed))) - - self.ctx.line_to(int(self.width-1-(((len(speeds)-1)*self.width)/(self.length-1))),int(self.height)-1 + lineWidth) - self.ctx.close_path() - - def drawSpeedPoly(self, speeds, color, maxSpeed, fill): - self.tracePath(speeds, maxSpeed) - self.ctx.set_source_rgba(color[0],color[1],color[2], color[3]) - - if fill: - self.ctx.fill() - else: - self.ctx.stroke() - - def drawLegend(self): - showDown = self.download_fill or self.download_line - showUp = self.upload_fill or self.upload_line - downBox_X = self.width-113 - - if showDown and showUp: - self.networkPixmap.draw_line(self.image.get_style().black_gc,self.width-186,1,self.width-186,21) - self.networkPixmap.draw_line(self.image.get_style().black_gc,self.width-185,21,self.width-1,21) - self.drawText("Download:",self.image.get_style().black_gc,self.width-181,2) - self.drawText("Upload:",self.image.get_style().black_gc,self.width-81,2) - elif showDown: - self.networkPixmap.draw_line(self.image.get_style().black_gc,self.width-103,1,self.width-103,21) - self.networkPixmap.draw_line(self.image.get_style().black_gc,self.width-102,21,self.width-1,21) - self.drawText("Download:",self.image.get_style().black_gc,self.width-98,2) - downBox_X = self.width-30 - elif showUp: - self.networkPixmap.draw_line(self.image.get_style().black_gc,self.width-86,1,self.width-86,21) - self.networkPixmap.draw_line(self.image.get_style().black_gc,self.width-85,21,self.width-1,21) - self.drawText("Upload:",self.image.get_style().black_gc,self.width-81,2) - - if self.download_fill and self.download_line: - self.drawRect(self.download_line_color,downBox_X,5,12,12) - self.drawRect(self.download_fill_color,downBox_X+12,5,12,12) - elif self.download_fill: - self.drawRect(self.download_fill_color,downBox_X,5,24,12) - elif self.download_line: - self.drawRect(self.download_line_color,downBox_X,5,24,12) - - if self.upload_fill and self.upload_line: - self.drawRect(self.upload_line_color,self.width-30,5,12,12) - self.drawRect(self.upload_fill_color,self.width-18,5,12,12) - elif self.upload_fill: - self.drawRect(self.upload_fill_color,self.width-30,5,24,12) - elif self.upload_line: - self.drawRect(self.upload_line_color,self.width-30,5,24,12) - - def drawText(self,text,color,x,y): - self.pangoLayout.set_text(text) - self.networkPixmap.draw_layout(color,x,y,self.pangoLayout) - - def drawRect(self,color,x,y,height,width): - self.ctx.set_source_rgba(color[0],color[1],color[2],color[3],) - self.ctx.rectangle(x,y,height,width) - self.ctx.fill() - - - - - - - - diff --git a/plugins/NetworkHealth/plugin.py b/plugins/NetworkHealth/plugin.py deleted file mode 100644 index 7dc195dea..000000000 --- a/plugins/NetworkHealth/plugin.py +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- -# -# plugin.py -# -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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. - -class plugin_NetworkHealth: - def __init__(self, path, deluge_core, deluge_interface): - print "Found NetworkHealth plugin..." - self.parent = deluge_interface # Using this, you can access the Deluge client - self.core = deluge_core - self.location = path - - self.counter = 30 - self.maxCount = self.counter - - def update(self): - session_info = self.core.get_state() - if not session_info['has_incoming_connections'] and \ - session_info['num_peers'] > 1: - message = "[No incoming connections]" - self.counter = self.counter - 1 - if self.counter < 0: - # self.parent.addMessage("No incoming connections: you may be behind a firewall or router. Perhaps you need to forward the relevant ports.", "W") - self.counter = self.maxCount*2 - self.maxCount = self.counter - else: - message = _("[Health: OK]") - self.counter = self.maxCount - - self.parent.statusbar_temp_msg = self.parent.statusbar_temp_msg + ' ' + message diff --git a/plugins/Scheduler/__init__.py b/plugins/Scheduler/__init__.py deleted file mode 100644 index 4fcd1f9f9..000000000 --- a/plugins/Scheduler/__init__.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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. - -# The name of the plugin -plugin_name = "Scheduler" -# The author's Name -plugin_author = "Lazka - updated by markybob and man_in_shack" -# The plugin's version number -plugin_version = "0.5.6.1" -# A description of the plugin -plugin_description = "Scheduler" - -def deluge_init(deluge_path): - global path - path = deluge_path - -from Scheduler.plugin import plugin_Scheduler - -def enable(core, interface): - global path - return plugin_Scheduler(path, core, interface) diff --git a/plugins/Scheduler/plugin.py b/plugins/Scheduler/plugin.py deleted file mode 100644 index c43bd2810..000000000 --- a/plugins/Scheduler/plugin.py +++ /dev/null @@ -1,335 +0,0 @@ -import deluge.common, deluge.pref, gtk, copy, pickle, time -import os.path - -class plugin_Scheduler: - def __init__(self, path, deluge_core, deluge_interface): - print "Found Scheduler plugin..." - self.path = path - self.core = deluge_core - self.interface = deluge_interface - - self.days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] - self.conf_file = os.path.join(deluge.common.CONFIG_DIR, "scheduler.conf") - self.config = deluge.pref.Preferences() - self.button_state_temp = [[0] * 7 for dummy in xrange(24)] - self.status = -1 - - #Load config - self.button_state = None - self.settings_structure = [["low_down", "max_download_speed", float], - ["low_up", "max_upload_speed", float], - ["high_down", "max_download_speed", float], - ["high_up", "max_upload_speed", float], - ["low_activetorrents", "max_active_torrents", float], - ["low_numslots", "max_upload_slots_global", float], - ["low_maxconns", "max_connections_global", float], - ["high_activetorrents", "max_active_torrents", float], - ["high_numslots", "max_upload_slots_global", float], - ["high_maxconns", "max_connections_global", float]] - - self.settings = {} - - try: - reader = open(self.conf_file, "rb") - data = pickle.load(reader) - - self.button_state = data[0] - for i, item in enumerate(self.settings_structure): - self.settings[item[0]] = data[1][i] - - reader.close() - except: - if self.button_state is None: - self.button_state = [[0] * 7 for dummy in xrange(24)] - - for item in self.settings_structure: - if item[0] not in self.settings: - temp = self.config.get(item[1]) - - if item[2] is not None: - temp = item[2](temp) - - self.settings[item[0]] = temp - - now = time.localtime(time.time()) - self.status = self.button_state[now[3]][now[6]] - self.prevhour = now[3] - - # Force speed changes when the plugin loads - self._state(self.status) - - def unload(self): - self.status = -1 - self.unlimit() - - def _state(self, state): - if state == 0: - self.unlimit() - elif state == 1: - self.limit() - elif state == 2: - self.pause() - - # Update the settings - self.status = state - - def update(self): - # Only do stuff if the status is valid - if self.status < 0: - return - - now = time.localtime(time.time()) - if now[3] != self.prevhour: - self.prevhour = now[3] - if not self.status == self.button_state[now[3]][now[6]]: - self._state(self.button_state[now[3]][now[6]]) - - def pause(self): - self.config.set("max_active_torrents", 0) - - def limit(self): - self.apply_configuration("low") - - def unlimit(self): - self.apply_configuration("high") - - def apply_configuration(self, type): - for item in self.settings_structure: - if item[0].find(type) == 0: - self.config.set(item[1], self.settings[item[0]]) - - self.core.apply_queue() - self.interface.apply_prefs() - - #Configuration dialog - def configure(self, window): - global scheduler_select - - self.button_state_temp = copy.deepcopy(self.button_state) - - #data - spin = {} - boxen = [ - ["down", _("Download limit:"), -1, 2048], - ["up", _("Upload limit:"), -1, 1024], - ["activetorrents", _("Active torrents:"), 0, 128], - ["numslots", _("Upload Slots:"), 0, 128], - ["maxconns", _("Max Connections:"), 0, 1024]] - - #dialog - dialog = gtk.Dialog(_("Scheduler Settings")) - dialog.set_default_size(600, 270) - - #buttons - cancel_button = dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) - ok_button = dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) - - #text - hover_text = gtk.Label() - - #Select Widget - drawing = scheduler_select(self.button_state_temp, hover_text, self.days) - - #boxes - vbox_main = gtk.VBox() - hbox_main = gtk.HBox() - vbox_sub = gtk.VBox() - hbox_key = gtk.HBox() - hbox_info = gtk.HBox() - hbox_settings = gtk.HBox() - # high boxen - tbl_high = gtk.Table(len(boxen), 2) - ebox_high = gtk.EventBox() - ebox_high.add(tbl_high) - ebrd_high = gtk.Frame() - ebrd_high.add(ebox_high) - ebrd_high.set_border_width(2) - tbl_high.set_border_width(2) - ebox_high.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse("#73D716")) - ebrd_high.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse("#53B700")) - # low boxen - tbl_low = gtk.Table(len(boxen), 2) - ebox_low = gtk.EventBox() - ebox_low.add(tbl_low) - ebrd_low = gtk.Frame() - ebrd_low.add(ebox_low) - ebrd_low.set_border_width(2) - tbl_low.set_border_width(2) - # Green - # Yellow - ebox_low.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse("#EDD400")) - ebrd_low.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse("#CDB400")) - - #seperator - sep = gtk.HSeparator() - - #pack - dialog.vbox.pack_start(vbox_main) - - vbox_main.pack_start(hbox_main) - vbox_main.pack_start(hover_text, False, True) - vbox_main.pack_start(hbox_key, False, True) - vbox_main.pack_start(hbox_info, False, True) - vbox_main.pack_start(sep, False, True) - vbox_main.pack_start(hbox_settings) - - hbox_main.pack_start(vbox_sub, False, True, 5) - hbox_main.pack_start(drawing) - - hbox_key.pack_start(gtk.Label(_("Green is the high limits, yellow is the low limits and red is stopped")), True, False) - hbox_info.pack_start(gtk.Label(_("If a limit is set to -1, it is unlimitted.")), True, False) - - hbox_settings.pack_start(ebrd_high, True, True, 5) - hbox_settings.pack_start(gtk.Label()) - hbox_settings.pack_start(ebrd_low, True, True, 5) - - for box in [tbl_high, tbl_low]: - for y, val in enumerate(boxen): - if box is tbl_high: type = "high" - else: type = "low" - key = type + "_" + val[0] - - label = gtk.Label(val[1]) - label.set_alignment(0.0, 0.6) - spin[key] = gtk.SpinButton() - spin[key].set_numeric(True) - spin[key].set_range(val[2], val[3]) - spin[key].set_increments(1, 10) - spin[key].set_value(self.settings[key]) - - box.attach(label, 0, 1, y, y + 1) - box.attach(spin[key], 1, 2, y, y + 1, False, False) - - for index in xrange(len(self.days)): - vbox_sub.pack_start(gtk.Label(self.days[index])) - - #show - dialog.show_all() - - #Save config - if dialog.run() == -5: - # Detect changes to the config - changed = False - if not self.button_state == drawing.button_state: - self.button_state = copy.deepcopy(drawing.button_state) - changed = True - - for key in spin.keys(): - if not self.settings[key] == spin[key].get_value(): - self.settings[key] = spin[key].get_value() - changed = True - - now = time.localtime(time.time()) - if changed: - self._state(self.button_state[now[3]][now[6]]) - - writer = open(self.conf_file, "wb") - - out = [] - - for item in self.settings_structure: - out.append(self.settings[item[0]]) - - pickle.dump([drawing.button_state, out], writer) - writer.close() - - dialog.destroy() - -class scheduler_select(gtk.DrawingArea): - - #connect signals - varaibles - def __init__(self, data, label, days): - gtk.DrawingArea.__init__(self) - self.set_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.LEAVE_NOTIFY_MASK) - - self.connect("expose_event", self.expose) - self.connect("button_press_event", self.mouse_down) - self.connect("button_release_event", self.mouse_up) - self.connect("motion_notify_event", self.mouse_hover) - self.connect("leave_notify_event", self.mouse_leave) - - self.colors = [[115.0/255, 210.0/255, 22.0/255], [237.0/255, 212.0/255, 0.0/255], [204.0/255, 0.0/255, 0.0/255]] - self.button_state = data - self.button_state_temp = [[0] * 7 for dummy in xrange(24)] - self.start_point = [0,0] - self.hover_point = [-1,-1] - self.hover_label = label - self.hover_days = days - self.mouse_press = False - - #redraw the whole thing - def expose(self, widget, event): - self.context = self.window.cairo_create() - self.context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) - self.context.clip() - - width = self.window.get_size()[0] - height = self.window.get_size()[1] - - for y in xrange(7): - for x in xrange(24): - self.context.set_source_rgba(self.colors[self.button_state[x][y]][0], self.colors[self.button_state[x][y]][1], self.colors[self.button_state[x][y]][2], 0.7) - self.context.rectangle(width*(6*x/145.0+1/145.0), height*(6*y/43.0+1/43.0), 5*width/145.0, 5*height/43.0) - self.context.fill_preserve() - self.context.set_source_rgba(0.5, 0.5, 0.5, 0.5) - self.context.stroke() - - #coordinates --> which box - def get_point(self, event): - size = self.window.get_size() - x = int((event.x-size[0]*0.5/145.0)/(6*size[0]/145.0)) - y = int((event.y-size[1]*0.5/43.0)/(6*size[1]/43.0)) - - if x > 23: x = 23 - elif x < 0: x = 0 - if y > 6: y = 6 - elif y < 0: y = 0 - - return [x,y] - - #mouse down - def mouse_down(self, widget, event): - self.mouse_press = True - self.start_point = self.get_point(event) - self.button_state_temp = copy.deepcopy(self.button_state) - - #if the same box -> change it - def mouse_up(self, widget, event): - self.mouse_press = False - end_point = self.get_point(event) - - #change color on mouseclick depending on the button - if end_point[0] is self.start_point[0] and end_point[1] is self.start_point[1]: - if event.button == 1: - self.button_state[end_point[0]][end_point[1]] += 1 - if self.button_state[end_point[0]][end_point[1]] > 2: - self.button_state[end_point[0]][end_point[1]] = 0 - elif event.button == 3: - self.button_state[end_point[0]][end_point[1]] -= 1 - if self.button_state[end_point[0]][end_point[1]] < 0: - self.button_state[end_point[0]][end_point[1]] = 2 - self.queue_draw() - - #if box changed and mouse is pressed draw all boxes from start point to end point - #set hover text etc.. - def mouse_hover(self, widget, event): - if self.get_point(event) != self.hover_point: - self.hover_point = self.get_point(event) - - self.hover_label.set_text(self.hover_days[self.hover_point[1]] + " " + str(self.hover_point[0]) + ":00 - " + str(self.hover_point[0]) + ":59") - - if self.mouse_press == True: - self.button_state = copy.deepcopy(self.button_state_temp) - - points = [[self.hover_point[0], self.start_point[0]], [self.hover_point[1], self.start_point[1]]] - - for x in xrange(min(points[0]), max(points[0])+1): - for y in xrange(min(points[1]), max(points[1])+1): - self.button_state[x][y] = self.button_state[self.start_point[0]][self.start_point[1]] - - self.queue_draw() - - #clear hover text on mouse leave - def mouse_leave(self, widget, event): - self.hover_label.set_text("") - self.hover_point = [-1,-1] diff --git a/plugins/Search/__init__.py b/plugins/Search/__init__.py deleted file mode 100644 index 058388e06..000000000 --- a/plugins/Search/__init__.py +++ /dev/null @@ -1,206 +0,0 @@ -# -*- coding: utf-8 -*- -# -# plugin.py -# -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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. - - -plugin_name = "Torrent Search" -plugin_author = "Marcos Pinto" -plugin_version = "0.3" -plugin_description = _("Search for torrents anonymously") - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return Search(path, core, interface) - -### The Plugin ### -import deluge -import deluge.common -import gtk -import os.path - -class Search: - def __init__(self, path, core, interface): - print "Found TorrentSearch plugin..." - import gtk, gtk.glade, os - import deluge.dgtk, deluge.pref - self.interface = interface - self.config_file = os.path.join(deluge.common.CONFIG_DIR, "newsearch.conf") - self.config = deluge.pref.Preferences(self.config_file, False, - defaults={'YouTorrent': 'http://www.youtorrent.com/tag/?q=${query}', - 'Pirate Bay' : 'http://thepiratebay.org/search/${query}/0/7/0', - 'Google' : "http://www.google.com/cse?cx=010331601\ -931556850092%3Apfadwhze_jy&q=${query}&sa=Search&cof=FORID%3A1", - 'Mininova' : 'http://www.mininova.org/search/?search=${query}/seeds', - 'isoHunt' : "http://isohunt.com/torrents/?ihq=${query}"}) - try: - self.config.load() - except IOError: - pass - - glade = gtk.glade.XML(path + "/searchdlg.glade") - self.dlg = glade.get_widget("search_dialog") - if not deluge.common.windows_check(): - self.dlg.set_icon(deluge.common.get_logo(18)) - self.view = glade.get_widget("search_view") - model = gtk.ListStore(str, str) - self.view.set_model(model) - deluge.dgtk.add_text_column(self.view, _("Name"), 0, width=80) - deluge.dgtk.add_text_column(self.view, _("Search String"), 1) - self.field_name = glade.get_widget("field_name") - self.field_search = glade.get_widget("field_search") - self.button_add = glade.get_widget("button_addsearch") - self.button_del = glade.get_widget("button_delsearch") - dic = { "add_clicked" : self.add_clicked, - "del_clicked" : self.del_clicked, - "row_clicked" : self.row_clicked, - "text_changed" : self.text_changed } - glade.signal_autoconnect(dic) - self.view.get_selection().set_select_function(self.row_clicked) - ### Note: All other plugins should use self.interface.toolbar - ### when adding items to the toolbar - self.se = '' - self.toolbar = self.interface.wtree.get_widget("tb_left") - self.search_entry = gtk.Entry() - self.search_entry.connect("activate", self.torrent_search) - self.search_item = gtk.ToolItem() - self.search_item.add(self.search_entry) - self.search_icon = gtk.Image() - self.search_icon.set_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_SMALL_TOOLBAR) - self.menu_button = gtk.MenuToolButton(self.search_icon, _("Choose an Engine")) - self.menu_button.set_is_important(True) - self.menu_button.connect("clicked", self.torrent_search) - self.menu = gtk.Menu() - self.manage_item = gtk.ImageMenuItem(_("Manage Engines")) - self.image = gtk.Image() - self.image.set_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_SMALL_TOOLBAR) - self.manage_item.set_image(self.image) - self.manage_item.connect("activate", self.configure) - self.menu.add(self.manage_item) - self.menu_button.set_menu(self.menu) - self.toolbar.insert(self.menu_button, -1) - self.toolbar.insert(self.search_item, -1) - self.populate_search_menu() - self.toolbar.show_all() - self.search_item.show_all() - self.menu_button.show_all() - self.menu.show_all() - - def unload(self): - self.config.save(self.config_file) - self.toolbar.remove(self.search_item) - self.toolbar.remove(self.menu_button) - - def text_changed(self, args): - a = (self.field_name.get_text() != "") - b = (self.field_search.get_text() != "") - if(a and b): - self.button_add.set_sensitive(1) - else: - self.button_add.set_sensitive(0) - - def add_clicked(self, args): - self.view.get_model().append([self.field_name.get_text(), - self.field_search.get_text()]) - self.field_name.set_text("") - self.field_search.set_text("") - - def del_clicked(self, args): - (model, selection) = self.view.get_selection().get_selected() - model.remove(selection) - self.button_del.set_sensitive(0) - - def row_clicked(self, args): - self.button_del.set_sensitive(1) - return True - - def configure(self, widget=None): - import gtk, gtk.glade - from deluge import common - self.dlg.show_all() - model = self.view.get_model() - model.clear() - for name in self.config.keys(): - self.view.get_model().append( (name, self.config.get(name)) ) - self.button_add.set_sensitive(0) - self.button_del.set_sensitive(0) - result = self.dlg.run() - self.dlg.hide_all() - if result == 1: - self.config.clear() - the_iter = model.get_iter_first() - while the_iter is not None: - self.config.set(model.get_value(the_iter, 0), model.get_value(the_iter, 1)) - the_iter = model.iter_next(the_iter) - self.config.save(self.config_file) - self.populate_search_menu() - - - def torrent_search(self, widget=None): - if self.search_entry.get_text() != "": - from deluge import common - print "Searching with engine", self.se - url = self.config.get(self.se) - entry = self.search_entry.get_text() - entry = entry.replace(' ', '+') - url = url.replace('${query}', entry) - print 'URL =', url - print 'Entry =', entry - common.open_url_in_browser(url) - - def populate_search_menu(self): - import gtk - self.menu_button.set_label(_("Choose an Engine")) - for child in self.menu.get_children(): - self.menu.remove(child) - group = None - i = 0 - for engine in self.config.keys(): - rmi = gtk.RadioMenuItem(None, engine) - rmi.eng_name = engine - rmi.connect("activate", self.select_search, rmi.eng_name) - if (group != None): - rmi.set_group(group) - else: - group = rmi - rmi.set_active(1) - self.menu.insert(rmi, i) - i = i + 1 - rmi.show() - self.menu.insert(self.manage_item, i) - self.menu.show() - - def select_search(self, menuitem, engine_string): - self.menu_button.set_label(_("Search ") + engine_string) - self.se = engine_string diff --git a/plugins/Search/searchdlg.glade b/plugins/Search/searchdlg.glade deleted file mode 100755 index 9e409df5c..000000000 --- a/plugins/Search/searchdlg.glade +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - 5 - Manage Search Plugins - False - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - 2 - - - True - 4 - 4 - - - True - gtk-add - True - - - - - 2 - 3 - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - GTK_POLICY_AUTOMATIC - - - True - - - - - 4 - - - - - True - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - - - - 1 - 4 - 2 - 3 - GTK_FILL - - - - - True - Name: - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - URL: - - - 2 - 3 - GTK_FILL - GTK_FILL - - - - - True - gtk-remove - True - - - - 3 - 4 - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - True - - - True - Add a new search engine by entering a Name and a URL. For Name, enter the name of the search engine to be used. For URL, enter the url of the seach page. The user's search query will replace any instance of ${query} in the URL. -For example, a Google search would be: -Name: Google -URL: http://www.google.com/search?q=${query} - True - - - - - True - Help - - - label_item - - - - - 4 - 3 - 4 - - - - - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - GTK_BUTTONBOX_END - - - True - gtk-cancel - True - - - - - True - gtk-ok - True - 1 - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/plugins/SpeedLimiter/__init__.py b/plugins/SpeedLimiter/__init__.py deleted file mode 100644 index ba06abd3b..000000000 --- a/plugins/SpeedLimiter/__init__.py +++ /dev/null @@ -1,211 +0,0 @@ -# Copyright (C) 2007 - Marcos Pinto -# -# 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 2, 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 St, Fifth Floor, Boston, MA 02110-1301 USA. - -plugin_name = "Speed Limiter" -plugin_author = "Marcos Pinto" -plugin_version = "0.1" -plugin_description = _("Set the desired speed limit per torrent.") - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return DesiredSpeed(path, core, interface) - -### The Plugin ### - -DEFAULT_PREFS = { - "up_speeds": [5, 10, 30, 80, 300], - "down_speeds": [5, 10, 30, 80, 300] -} - -import deluge -import gtk, gtk.glade -import os.path - -class DesiredSpeed: - - def __init__(self, path, core, interface): - print "Found SpeedLimiter plugin..." - self.path = path - self.core = core - self.interface = interface - self.set_up_speeds = {} - self.set_down_speeds = {} - self.callback_ids = [] - - self.config = deluge.pref.Preferences(filename=os.path.join(deluge.common.CONFIG_DIR, "desired_speed.conf"), global_defaults=False, defaults=DEFAULT_PREFS) - - self.callback_ids.append(self.interface.torrent_menu.connect_after("realize", self.torrent_menu_show)) - self.callback_ids.append(self.interface.torrent_menu.connect("show", self.torrent_menu_show)) - self.callback_ids.append(self.interface.torrent_menu.connect("hide", self.torrent_menu_hide)) - for torrent in self.core.get_queue(): - unique_ID = self.core.get_torrent_unique_id(torrent) - try: - if self.core.unique_IDs[unique_ID].upload_rate_limit != -1: - value = int(self.core.unique_IDs[unique_ID].upload_rate_limit) - self.core.set_per_upload_rate_limit(unique_ID, value) - self.set_up_speeds[unique_ID] = value - if value not in self.config.get("up_speeds") and value >= 1: - self.config.get("up_speeds").insert(0, value) - self.config.get("up_speeds").pop() - if self.core.unique_IDs[unique_ID].download_rate_limit != -1: - value = int(self.core.unique_IDs[unique_ID].download_rate_limit) - self.core.set_per_download_rate_limit(unique_ID, value) - self.set_down_speeds[unique_ID] = value - if value not in self.config.get("down_speeds") and value >= 1: - self.config.get("down_speeds").insert(0, value) - self.config.get("down_speeds").pop() - except AttributeError: - pass - - def torrent_menu_show(self, widget, data=None): - self.unique_ID = self.interface.get_selected_torrent() - - self.down_image = gtk.Image() - self.down_image.set_from_file(deluge.common.get_pixmap('downloading16.png')) - self.down_speed_menuitem = gtk.ImageMenuItem(_("Torrent _Download Speed")) - self.down_speed_menuitem.set_image(self.down_image) - self.down_speed_menu = self.interface.build_menu_radio_list(self.config.get("down_speeds"), self.down_speed_clicked, self.get_torrent_desired_down_speed(), suffix=_("KiB/s"), show_notset=True, notset_lessthan=0, show_other=True) - - self.down_speed_menuitem.set_submenu(self.down_speed_menu) - self.interface.torrent_menu.append(self.down_speed_menuitem) - self.down_speed_menuitem.show_all() - - self.up_image = gtk.Image() - self.up_image.set_from_file(deluge.common.get_pixmap('seeding16.png')) - self.up_speed_menuitem = gtk.ImageMenuItem(_("Torrent Upload _Speed")) - self.up_speed_menuitem.set_image(self.up_image) - self.up_speed_menu = self.interface.build_menu_radio_list(self.config.get("up_speeds"), self.up_speed_clicked, self.get_torrent_desired_up_speed(), suffix=_("KiB/s"), show_notset=True, notset_lessthan=0, show_other=True) - - self.up_speed_menuitem.set_submenu(self.up_speed_menu) - self.interface.torrent_menu.append(self.up_speed_menuitem) - self.up_speed_menuitem.show_all() - - def torrent_menu_hide(self, widget): - try: - self.interface.torrent_menu.remove(self.up_speed_menuitem) - self.interface.torrent_menu.remove(self.down_speed_menuitem) - except AttributeError: - pass - - def update(self): - pass - - def unload(self): - # Disconnect all callbacks - for callback_id in self.callback_ids: - try: - self.interface.torrent_menu.disconnect(callback_id) - except: - pass - - self.callback_ids = [] - - # Reset all desired speeds in the core - for unique_ID, speed in self.set_up_speeds.items(): - if speed >= 0: - try: - self.core.set_per_upload_rate_limit(unique_ID, int(-1)) - except: - pass - self.set_up_speeds = {} - - for unique_ID, speed in self.set_down_speeds.items(): - if speed >= 0: - try: - self.core.set_per_download_rate_limit(unique_ID, int(-1)) - except: - pass - self.set_down_speeds = {} - - def up_speed_clicked(self, widget): - value = widget.get_children()[0].get_text().rstrip(" "+_("KiB/s")) - if value == _("Unlimited"): - value = -1 - - if value == _("Other..."): - dialog_glade = gtk.glade.XML(deluge.common.get_glade_file("dgtkpopups.glade")) - speed_dialog = dialog_glade.get_widget("speed_dialog") - spin_title = dialog_glade.get_widget("spin_title") - spin_title.set_text(_("Torrent Upload Speed (KiB/s):")) - spin_speed = dialog_glade.get_widget("spin_speed") - spin_speed.set_value(self.get_torrent_desired_up_speed()) - spin_speed.select_region(0, -1) - response = speed_dialog.run() - if response == 1: # OK Response - value = spin_speed.get_value() - else: - speed_dialog.destroy() - return - speed_dialog.destroy() - - value = int(value) - - self.core.set_per_upload_rate_limit(self.unique_ID, value) - self.set_up_speeds[self.unique_ID] = value - self.core.unique_IDs[self.unique_ID].upload_rate_limit = value - - # Update the speeds list if necessary - if value not in self.config.get("up_speeds") and value >= 1: - self.config.get("up_speeds").insert(0, value) - self.config.get("up_speeds").pop() - - def down_speed_clicked(self, widget): - value = widget.get_children()[0].get_text().rstrip(" "+_("KiB/s")) - if value == _("Unlimited"): - value = -1 - - if value == _("Other..."): - dialog_glade = gtk.glade.XML(deluge.common.get_glade_file("dgtkpopups.glade")) - speed_dialog = dialog_glade.get_widget("speed_dialog") - spin_title = dialog_glade.get_widget("spin_title") - spin_title.set_text(_("Torrent Download Speed (KiB/s):")) - spin_speed = dialog_glade.get_widget("spin_speed") - spin_speed.set_value(self.get_torrent_desired_down_speed()) - spin_speed.select_region(0, -1) - response = speed_dialog.run() - if response == 1: # OK Response - value = spin_speed.get_value() - else: - speed_dialog.destroy() - return - speed_dialog.destroy() - - value = int(value) - - self.core.set_per_download_rate_limit(self.unique_ID, value) - self.set_down_speeds[self.unique_ID] = value - self.core.unique_IDs[self.unique_ID].download_rate_limit = value - - # update the speeds list if necessary - if value not in self.config.get("down_speeds") and value >= 0: - self.config.get("down_speeds").insert(0, value) - self.config.get("down_speeds").pop() - - def get_torrent_desired_up_speed(self): - if self.set_up_speeds.has_key(self.unique_ID): - return self.set_up_speeds[self.unique_ID] - else: - return -1 - - def get_torrent_desired_down_speed(self): - if self.set_down_speeds.has_key(self.unique_ID): - return self.set_down_speeds[self.unique_ID] - else: - return -1 diff --git a/plugins/TorrentCreator/__init__.py b/plugins/TorrentCreator/__init__.py deleted file mode 100644 index e242a536a..000000000 --- a/plugins/TorrentCreator/__init__.py +++ /dev/null @@ -1,165 +0,0 @@ -# Copyright (C) 2007 - Andrew Resch -# -# 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 2, 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 St, Fifth Floor, Boston, MA 02110-1301 USA. - -### Initialization ### - -plugin_name = "Torrent Creator" -plugin_author = "Andrew Resch" -plugin_version = "0.1" -plugin_description = _("A torrent creator plugin") - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return TorrentCreator(path, core, interface) - -### The Plugin ### - -import deluge -import gtk, gtk.glade -import os.path - -class TorrentCreator: - - def __init__(self, path, core, interface): - print "Found TorrentCreator plugin..." - self.path = path - self.core = core - self.interface = interface - self.glade = None - - # Add 'New Torrent' menu item to the File menu - self.menuitem_image = gtk.Image() - self.menuitem_image.set_from_stock(gtk.STOCK_NEW, gtk.ICON_SIZE_MENU) - - self.menuitem = gtk.ImageMenuItem(_("_New Torrent")) - self.menuitem.set_image(self.menuitem_image) - self.menuitem.connect("activate", self.new_torrent_clicked) - self.interface.wtree.get_widget("menu_file").get_submenu().prepend(self.menuitem) - self.menuitem.show_all() - - # Add a 'New Torrent' button to the toolbar - self.toolbutton_image = gtk.Image() - self.toolbutton_image.set_from_stock(gtk.STOCK_NEW, gtk.ICON_SIZE_MENU) - - self.toolbutton = gtk.ToolButton(self.toolbutton_image, _("New Torrent")) - self.toolbutton_tip = gtk.Tooltips() - self.toolbutton.set_tooltip(self.toolbutton_tip, _("Create New Torrent")) - self.toolbutton.connect("clicked", self.new_torrent_clicked) - self.interface.wtree.get_widget("tb_left").insert(self.toolbutton, 0) - self.toolbutton.show_all() - - def destroy(self, data=None): - self.dialog.hide() - self.dialog.destroy() - - def update(self): - pass - - def unload(self): - print "Unloading TorrentCreator plugin..." - self.interface.wtree.get_widget("menu_file").get_submenu().remove(self.menuitem) - self.interface.wtree.get_widget("tb_left").remove(self.toolbutton) - - - def new_torrent_clicked(self, widget, data=None): - # Show the torrent creator dialog - self.glade = gtk.glade.XML(os.path.join(self.path, "torrentcreator.glade")) - - self.dialog = self.glade.get_widget("torrentcreator") - self.glade.get_widget("piece_size_combobox").set_active(3) - self.glade.get_widget("torrent_chooserbutton").connect("clicked", self.torrent_chooserbutton_clicked) - self.glade.get_widget("ok_button").connect("clicked", self.create_torrent) - self.glade.get_widget("close_button").connect("clicked", self.destroy) - self.dialog.show_all() - response = self.dialog.run() - - if response == 0: - self.destroy() - - return - - def torrent_chooserbutton_clicked(self, widget): - filechooser = gtk.FileChooserDialog(title=_("Save file as..."), - parent=None, action=gtk.FILE_CHOOSER_ACTION_SAVE, - buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - gtk.STOCK_OK, gtk.RESPONSE_OK), backend=None) - response = filechooser.run() - # Update the torrentfile entry widget if a file was selected. - if response == gtk.RESPONSE_OK: - torrent = filechooser.get_filename() - if not torrent.endswith(".torrent"): - torrent += ".torrent" - self.glade.get_widget("torrentfile_entry").set_text(torrent) - - filechooser.destroy() - - def create_torrent(self, widget): - # Create a torrent from the information provided in the torrentcreator dialog - if self.glade.get_widget("folder_radiobutton").get_active(): - source = self.glade.get_widget("folder_chooserbutton").get_filename() - else: - source = self.glade.get_widget("file_chooserbutton").get_filename() - - if source == "" or source == None: - deluge.dialogs.show_popup_warning(self.dialog, _("You must select a source for the torrent.")) - return False - - torrent = self.glade.get_widget("torrentfile_entry").get_text() - - if torrent == "" or torrent == None: - # Send alert to the user that we need a torrent filename to save to - deluge.dialogs.show_popup_warning(self.dialog, _("You must select a file to save the torrent as.")) - return False - - piece_size = self.glade.get_widget("piece_size_combobox") - piece_size = int(piece_size.get_model().get_value(piece_size.get_active_iter(), 0).split(" ")[0]) - - trackers = self.glade.get_widget("trackers_textview").get_buffer() - (start, end) = trackers.get_bounds() - trackers = trackers.get_text(start, end).strip() - - webseeds = self.glade.get_widget("webseeds_textview").get_buffer() - (start, end) = webseeds.get_bounds() - webseeds = webseeds.get_text(start, end).strip() - - comments = self.glade.get_widget("comments_textview").get_buffer() - (start, end) = comments.get_bounds() - comments = comments.get_text(start, end).strip() - - author = self.glade.get_widget("author_entry").get_text() - - if author == "" or author == None: - author = _("Deluge") - - add_torrent = self.glade.get_widget("add_torrent_checkbox").get_active() - set_private = self.glade.get_widget("chk_set_priv").get_active() - # Destroy the dialog.. we don't need it anymore - self.destroy() - - # Create the torrent and add it to the queue if necessary - if self.core.create_torrent(torrent, source, trackers, comments, - piece_size, author, set_private, webseeds) == 1: - # Torrent was created successfully - if add_torrent: - # We need to add this torrent to the queue - self.interface.interactive_add_torrent(torrent) - return True - else: - return False diff --git a/plugins/TorrentCreator/torrentcreator.glade b/plugins/TorrentCreator/torrentcreator.glade deleted file mode 100644 index 315098650..000000000 --- a/plugins/TorrentCreator/torrentcreator.glade +++ /dev/null @@ -1,592 +0,0 @@ - - - - - - 550 - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Torrent Creator - GTK_WIN_POS_CENTER_ON_PARENT - 400 - 500 - True - GDK_WINDOW_TYPE_HINT_DIALOG - False - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 5 - 5 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_RESIZE_QUEUE - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - 10 - 12 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 5 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 1 - 2 - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER - - - 1 - 2 - GTK_FILL - - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - This torrent will be made from a single file - File: - 0 - True - folder_radiobutton - - - 1 - 2 - - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - This torrent will be made from a directory - Folder: - 0 - True - True - - - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Source</b> - True - - - label_item - - - - - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 5 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 1 - 3 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Save Torrent File As: - - - - - GTK_FILL - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - gtk-open - 2 - - - - - 2 - 3 - - - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - - - - - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Load this torrent into Deluge for seeding - Add new torrent to queue - 0 - True - True - - - False - False - 1 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Torrent File</b> - True - - - label_item - - - - - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - GTK_RESIZE_QUEUE - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_WRAP_CHAR - False - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Trackers</b> - True - - - label_item - - - - - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - GTK_RESIZE_QUEUE - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_WRAP_CHAR - False - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Web Seeds</b> - True - - - label_item - - - - - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - GTK_RESIZE_QUEUE - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_WRAP_WORD_CHAR - False - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Comments</b> - True - - - label_item - - - - - 4 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 12 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Author</b> - True - - - label_item - - - - - False - 5 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 22 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 2 - 10 - - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Set Private Flag - 0 - True - - - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The smaller the piece sizes, the more efficient the transfers will be, but the actual ".torrent" file will be larger - 32 KiB -64 KiB -128 KiB -256 KiB -512 KiB -1024 KiB -2048 KiB - - - - 1 - 2 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - The smaller the piece sizes, the more efficient the transfers will be, but the actual ".torrent" file will be larger - 0 - Piece Size: - - - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Advanced</b> - True - - - label_item - - - - - False - False - 6 - - - - - - - - - - - - - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_BUTTONBOX_END - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-close - True - 0 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-save - True - 1 - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/plugins/TorrentFiles/__init__.py b/plugins/TorrentFiles/__init__.py deleted file mode 100644 index 75118ff48..000000000 --- a/plugins/TorrentFiles/__init__.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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. - -### Initialization ### - -plugin_name = "Torrent Files" -plugin_author = "Deluge" -plugin_version = "0.2" -plugin_description = _(""" -This plugin shows you the files inside a torrent and allows you to set \ -priorities for them and choose which ones you want or don't want to download. -""") - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return TorrentFiles(path, core, interface) - -### The Plugin ### -import gtk - -import deluge -from TorrentFiles.tab_files import FilesTabManager -import os.path - -class TorrentFiles: - def __init__(self, path, core, interface): - print "Found TorrentFiles plugin..." - self.parent = interface - self.manager = core - config_file = os.path.join(deluge.common.CONFIG_DIR, "files.conf") - self.config = deluge.pref.Preferences(config_file, False, - defaults={'file_viewer': 'xdg-open'}) - try: - self.config.load() - except IOError: - # File does not exist - pass - - self.glade = gtk.glade.XML(os.path.join(path, "files_preferences.glade")) - self.dialog = self.glade.get_widget("dialog") - self.glade.signal_autoconnect({ - 'on_button_cancel_clicked': self.on_button_cancel_clicked, - 'on_button_ok_clicked': self.on_button_ok_clicked - }) - - tree_view = gtk.TreeView() - tree_view.set_rules_hint(True) - scrolled_window = gtk.ScrolledWindow() - scrolled_window.add(tree_view) - scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.top_widget = scrolled_window - - self.parent_notebook = self.parent.notebook - self.parent_notebook.append_page(scrolled_window, - gtk.Label(_("Files"))) - - tree_view.show() - scrolled_window.show() - - self.tab_files = FilesTabManager(tree_view, core) - self.tab_files.build_file_view() - self.tab_files.set_file_viewer(self.config.get("file_viewer")) - - def unload(self): - self.tab_files.clear_file_store() - tab_page = self.parent_notebook.page_num(self.top_widget) - self.parent_notebook.remove_page(tab_page) - self.config.save() - - def update(self): - if not self.parent.update_interface: - return - - tab_page = self.parent_notebook.page_num(self.top_widget) - current_page = self.parent_notebook.get_current_page() - - if tab_page == current_page: - unique_id = self.parent.get_selected_torrent() - - if unique_id is None or \ - unique_id in self.manager.removed_unique_ids: - # If no torrents added or more than one torrent selected - self.tab_files.clear_file_store() - self.tab_files.set_unique_id(None) - return - - if self.tab_files.file_unique_id != unique_id: - self.tab_files.clear_file_store() - self.tab_files.set_unique_id(unique_id) - self.tab_files.prepare_file_store() - else: - self.tab_files.update_file_store() - - def configure(self, window): - self.glade.get_widget("file_viewer").\ - set_text(self.config.get("file_viewer")) - if deluge.common.windows_check(): - self.glade.get_widget("file_viewer").set_sensitive(False) - self.dialog.set_transient_for(window) - self.dialog.show() - - def on_button_ok_clicked(self, button): - self.dialog.hide() - - self.config.set("file_viewer", - self.glade.get_widget("file_viewer").get_text()) - self.config.save() - - self.tab_files.set_file_viewer(self.config.get("file_viewer")) - - def on_button_cancel_clicked(self, button): - self.dialog.hide() diff --git a/plugins/TorrentFiles/files_preferences.glade b/plugins/TorrentFiles/files_preferences.glade deleted file mode 100644 index 4193f9a99..000000000 --- a/plugins/TorrentFiles/files_preferences.glade +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Files Preferences - GTK_WIN_POS_CENTER_ON_PARENT - GDK_WINDOW_TYPE_HINT_NORMAL - True - True - False - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - This preference is only used on non-Windows systems - - - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - File Viewer: - - - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - - - - - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_BUTTONBOX_END - - - True - - gtk-cancel - True - 0 - - - - - - True - - gtk-ok - True - 0 - - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/plugins/TorrentFiles/tab_files.py b/plugins/TorrentFiles/tab_files.py deleted file mode 100644 index eb7917fc5..000000000 --- a/plugins/TorrentFiles/tab_files.py +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: utf-8 -*- -# -# tab_files.py -# -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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 itertools import izip - -import gobject -import gtk - -from deluge.files import FilesBaseManager -from deluge import dgtk, dialogs - -class FilesTabManager(FilesBaseManager): - def __init__(self, file_view, manager): - file_store = gtk.ListStore(str, gobject.TYPE_UINT64, - gobject.TYPE_UINT, float, str) - - super(FilesTabManager, self).__init__(file_view, file_store) - self.manager = manager - self.file_unique_id = None - - # Stores file path -> gtk.TreeIter's iter mapping for quick look up - # in self.update_file_store() - self.file_store_dict = {} - - self.file_viewer = None - - def build_file_view(self): - super(FilesTabManager, self).build_file_view() - - percent_col = dgtk.add_progress_column(self.file_view, _("Progress"),\ - 3, 4, width=150) - expander_col = gtk.TreeViewColumn() - expander_col.set_expand(True) - self.file_view.append_column(expander_col) - self.file_view.connect("row-activated", self.double_click_file) - - def set_unique_id(self, unique_id): - self.file_unique_id = unique_id - - def priority_clicked(self, widget): - if self.manager.get_pref("use_compact_storage"): - self.compact_allocation_warning() - else: - super(FilesTabManager, self).priority_clicked(widget) - - def set_file_viewer(self, file_viewer): - self.file_viewer = file_viewer - - def double_click_file(self, tree, path, view_column): - self.open_file() - - def open_file(self, widget=None): - import os - - from deluge.common import exec_command, windows_check - - save_dir = self.manager.unique_IDs[self.file_unique_id].save_dir - selected_paths = self.file_view.get_selection().get_selected_rows()[1] - try: - for path in selected_paths: - child_path = self.file_store_sorted.\ - convert_path_to_child_path(path) - file_name = self.file_store.get_value( - self.file_store.get_iter(child_path), 0) - if windows_check(): - try: - os.startfile(os.path.join(save_dir, file_name)) - except WindowsError: - import gtk - gtk.gdk.threads_enter() - result = dialogs.show_popup_warning(None, _("There was \ -an error trying to launch the file.")) - gtk.gdk.threads_leave() - else: - exec_command(self.file_viewer, - os.path.join(save_dir, file_name)) - except KeyError: - pass - - # From core to UI - def prepare_file_store(self): - if not self.file_store_dict: - all_files = self.manager.get_torrent_file_info(self.file_unique_id) - file_priorities = self.manager.get_priorities(self.file_unique_id) - for file, priority in izip(all_files, file_priorities): - iter = self.file_store.append([file['path'], file['size'], - priority, file['progress'], - "%.3g%%"%float(file['progress'])]) - self.file_store_dict[file['path']] = iter - - # From core to UI - def update_file_store(self): - new_file_info = self.manager.get_torrent_file_info(self.file_unique_id) - for file in new_file_info: - iter = self.file_store_dict[file['path']] - dgtk.update_store(self.file_store, iter, (3,4), - (file['progress'], - "%.3g%%"%float(file['progress']))) - - # From UI to core - def update_priorities(self): - prev_file_priorities = self.manager.get_priorities(self.file_unique_id) - file_priorities = [] - update = False - for x, priority in izip(self.file_store, prev_file_priorities): - file_priorities.append(x[2]) - if x[2] > 0 and priority == 0: - update = True - if x[2] == 0: - update = True - self.manager.prioritize_files(self.file_unique_id, file_priorities, update_files_removed=update) diff --git a/plugins/TorrentNotification/__init__.py b/plugins/TorrentNotification/__init__.py deleted file mode 100644 index 4aba15726..000000000 --- a/plugins/TorrentNotification/__init__.py +++ /dev/null @@ -1,166 +0,0 @@ -# Copyright (C) 2007 - Micah Bucy -# -# 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 2, 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 St, Fifth Floor, Boston, MA 02110-1301 USA. - -### Initialization ### - -plugin_name = "Torrent Notification" -plugin_author = "Micah Bucy" -plugin_version = "0.1" -plugin_description = _("Make tray icon blink when torrent finishes downloading \ -and/or popup a notification") - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return TorrentNotification(path, core, interface) - -### The Plugin ### -import deluge -import deluge.common -import gtk -import os.path - -class TorrentNotification: - - def __init__(self, path, core, interface): - print "Found TorrentNotification plugin..." - import os.path - self.path = path - self.core = core - self.interface = interface - self.window = self.interface.window - self.window.connect("focus_in_event", self.set_tray_flashing_off) - self.core.connect_event(self.core.constants['EVENT_FINISHED'], self.handle_event) - - # Create an options file and try to load existing Values - self.config_file = os.path.join(deluge.common.CONFIG_DIR, "notification.conf") - if deluge.common.windows_check(): - self.config = deluge.pref.Preferences(self.config_file, False, - defaults={'enable_tray_blink' : True, - 'enable_notification' : False, - 'enable_sound' : False, - 'sound_path' : os.path.expanduser("~")}) - else: - self.config = deluge.pref.Preferences(self.config_file, False, - defaults={'enable_tray_blink' : True, - 'enable_notification' : True, - 'enable_sound' : False, - 'sound_path' : os.path.expanduser("~")}) - try: - self.config.load() - except IOError: - pass - - self.glade = gtk.glade.XML(os.path.join(path, "notification_preferences.glade")) - self.dialog = self.glade.get_widget("dialog") - self.dialog.set_position(gtk.WIN_POS_CENTER) - self.glade.signal_autoconnect({ - 'toggle_ui': self.toggle_ui, - 'dialog_ok': self.dialog_ok, - 'dialog_cancel': self.dialog_cancel - }) - - def handle_event(self, event): - if event['message'] == "torrent has finished downloading": - if self.config.get("enable_tray_blink"): - self.set_tray_flashing_on() - if self.config.get("enable_notification"): - self.show_notification(event) - if self.config.get("enable_sound"): - self.play_sound() - - def unload(self): - self.core.disconnect_event(self.core.constants['EVENT_FINISHED'], self.handle_event) - self.config.save(self.config_file) - - def set_tray_flashing_off(self, focusdata1, focusdata2): - self.interface.tray_icon.set_blinking(False) - - def set_tray_flashing_on(self): - if self.window.has_toplevel_focus() is not True: - self.interface.tray_icon.set_blinking(True) - - def show_notification(self, event): - if not deluge.common.windows_check(): - try: - import pynotify - except: - pass - else: - state = self.interface.manager.get_torrent_state(event['unique_ID']) - if pynotify.init("Deluge"): - n = pynotify.Notification(_("Torrent complete"), state['name']) - n.set_icon_from_pixbuf(deluge.common.get_logo(48)) - if not n.show(): - print "Failed to send notification" - else: - pass - - def configure(self, window): - self.glade.get_widget("chk_tray_blink").set_active(self.config.get("enable_tray_blink")) - if deluge.common.windows_check(): - self.glade.get_widget("chk_notification").set_active(False) - self.glade.get_widget("chk_notification").set_sensitive(False) - self.glade.get_widget("chk_sound").set_active(False) - self.glade.get_widget("chk_sound").set_sensitive(False) - self.glade.get_widget("sound_path_button").set_sensitive(False) - else: - self.glade.get_widget("chk_notification").set_active(self.config.get("enable_notification")) - self.glade.get_widget("chk_sound").set_active(self.config.get("enable_sound")) - self.glade.get_widget("sound_path_button").set_sensitive(self.config.get("enable_sound")) - self.glade.get_widget("sound_path_button").set_filename(self.config.get("sound_path")) - self.dialog.set_transient_for(window) - self.dialog.show() - - def dialog_ok(self, source): - self.dialog.hide() - self.config.set("enable_tray_blink", self.glade.get_widget("chk_tray_blink").get_active()) - self.config.set("enable_notification", self.glade.get_widget("chk_notification").get_active()) - self.config.set("enable_sound", self.glade.get_widget("chk_sound").get_active()) - self.config.set("sound_path", self.glade.get_widget("sound_path_button").get_filename()) - - def dialog_cancel(self, source): - self.dialog.hide() - - def toggle_ui(self, widget): - value = widget.get_active() - if widget == self.glade.get_widget("chk_sound"): - self.glade.get_widget("sound_path_button").set_sensitive(value) - - def play_sound(self): - if not deluge.common.windows_check(): - try: - import pygame - except: - pass - else: - import sys - pygame.init() - try: - name = self.config.get("sound_path") - except: - print "no file set" - try: - alert_sound = pygame.mixer.music - alert_sound.load(name) - alert_sound.play() - except pygame.error, message: - print 'Cannot load sound:' - else: - pass diff --git a/plugins/TorrentNotification/notification_preferences.glade b/plugins/TorrentNotification/notification_preferences.glade deleted file mode 100644 index edb8ade42..000000000 --- a/plugins/TorrentNotification/notification_preferences.glade +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - 5 - Torrent Notification Preferences - 400 - 150 - True - GDK_WINDOW_TYPE_HINT_NORMAL - True - True - False - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - 2 - - - True - 3 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - Enable event sound (requires pygame, not available on Win32) - True - 0 - True - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - - - - - 2 - 3 - - - - - True - True - Enable blinking tray icon - True - 0 - True - - - - - True - True - Enable popup notification (requires python-notify, not available on Win32) - True - 0 - True - - - 1 - 2 - - - - - False - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - GTK_BUTTONBOX_END - - - True - gtk-cancel - True - 0 - - - - - - True - gtk-ok - True - 1 - - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/plugins/TorrentPeers/__init__.py b/plugins/TorrentPeers/__init__.py deleted file mode 100644 index ee7188afa..000000000 --- a/plugins/TorrentPeers/__init__.py +++ /dev/null @@ -1,189 +0,0 @@ -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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. - -### Initialization ### - -plugin_name = "Torrent Peers" -plugin_author = "Deluge" -plugin_version = "0.2" -plugin_description = _(""" -This shows you the peers associated with each torrent and shows you their ip, \ -country, client, percent complete and upload and download speeds. -""") - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return TorrentPeers(path, core, interface) - -### The Plugin ### -import gtk - -import deluge -from TorrentPeers.tab_peers import PeersTabManager -import os.path - -class TorrentPeers: - - def __init__(self, path, core, interface): - print "Found TorrentPeers plugin..." - self.parent = interface - self.manager = core - self.config_file = os.path.join(deluge.common.CONFIG_DIR, "peers.conf") - self.config = deluge.pref.Preferences(self.config_file, False, - defaults={'enable_flags' : True, - 'size_18' : True}) - try: - self.config.load() - except IOError: - # File does not exist - pass - self.dialog_initialize = True - self.glade = gtk.glade.XML(os.path.join(path, "peers_preferences.glade")) - self.dialog = self.glade.get_widget("dialog") - self.glade.signal_autoconnect({ - 'toggle_ui': self.toggle_ui, - 'on_button_cancel_clicked': self.cancel_clicked, - 'on_button_ok_clicked': self.ok_clicked - }) - tree_view = gtk.TreeView() - scrolled_window = gtk.ScrolledWindow() - scrolled_window.add(tree_view) - scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.top_widget = scrolled_window - - self.parent_notebook = self.parent.notebook - self.parent_notebook.append_page(self.top_widget, - gtk.Label(_("Peers"))) - - tree_view.show() - scrolled_window.show() - - self.tab_peers = PeersTabManager(tree_view, core) - self.tab_peers.build_peers_view() - - self.config_updated() - - def unload(self): - self.tab_peers.clear_peer_store() - tab_page = self.parent_notebook.page_num(self.top_widget) - self.parent_notebook.remove_page(tab_page) - self.config.save(self.config_file) - - def configure(self, window): - self.dialog_initialize = True - if self.config.get("enable_flags"): - self.glade.get_widget("chk_flags").set_active(True) - self.glade.get_widget("radio_18").set_sensitive(True) - self.glade.get_widget("radio_25").set_sensitive(True) - if self.config.get("size_18"): - self.glade.get_widget("radio_18").set_active(True) - self.glade.get_widget("radio_25").set_active(False) - else: - self.glade.get_widget("radio_18").set_active(False) - self.glade.get_widget("radio_25").set_active(True) - else: - self.glade.get_widget("chk_flags").set_active(False) - self.glade.get_widget("radio_18").set_sensitive(False) - self.glade.get_widget("radio_25").set_sensitive(False) - - self.dialog_initialize = False - self.dialog.set_transient_for(window) - self.dialog.show() - - def config_updated(self): - if self.config.get("enable_flags"): - self.tab_peers.enable_flags() - if self.config.get("size_18"): - if self.tab_peers.flag_size == "25x15": - self.tab_peers.clear_flag_cache() - self.tab_peers.set_flag_size("18x12") - else: - if self.tab_peers.flag_size == "18x12": - self.tab_peers.clear_flag_cache() - self.tab_peers.set_flag_size("25x15") - else: - self.tab_peers.clear_flag_cache() - self.tab_peers.disable_flags() - - def toggle_ui(self, widget): - if not self.dialog_initialize: - value = widget.get_active() - if widget == self.glade.get_widget("chk_flags"): - if value: - self.glade.get_widget("radio_18").set_sensitive(True) - self.glade.get_widget("radio_25").set_sensitive(True) - else: - self.glade.get_widget("radio_18").set_sensitive(False) - self.glade.get_widget("radio_25").set_sensitive(False) - - def update(self): - if not self.parent.update_interface: - return - - tab_page = self.parent_notebook.page_num(self.top_widget) - current_page = self.parent_notebook.get_current_page() - - if tab_page == current_page: - unique_id = self.parent.get_selected_torrent() - if unique_id is None or \ - unique_id in self.manager.removed_unique_ids: - #if no torrents added or more than one torrent selected - self.tab_peers.clear_peer_store() - self.tab_peers.set_unique_id(None) - return - if self.tab_peers.peer_unique_id != unique_id: - self.tab_peers.clear_peer_store() - self.tab_peers.set_unique_id(unique_id) - self.tab_peers.update_peer_store() - else: - self.tab_peers.update_peer_store() - - def ok_clicked(self, src): - self.dialog.hide() - - needs_store_update = False - if self.config.get("enable_flags") and not \ - self.glade.get_widget("chk_flags").get_active(): - needs_store_update = True - - self.config.set("enable_flags", - self.glade.get_widget("chk_flags").get_active()) - self.config.set("size_18", - self.glade.get_widget("radio_18").get_active()) - self.config_updated() - - if needs_store_update: - self.tab_peers.update_peer_store() - self.tab_peers.ip_column_queue_resize() - - def cancel_clicked(self, src): - self.dialog.hide() diff --git a/plugins/TorrentPeers/peers_preferences.glade b/plugins/TorrentPeers/peers_preferences.glade deleted file mode 100644 index 55d33c70a..000000000 --- a/plugins/TorrentPeers/peers_preferences.glade +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - 5 - Peers Preferences - 400 - 150 - GDK_WINDOW_TYPE_HINT_NORMAL - True - True - True - False - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - 2 - - - True - 4 - - - True - True - Enable flags - True - 0 - True - - - - - - True - Select size of flag - - - 1 - 2 - - - - - True - 18x12 - True - 0 - True - - - - 2 - 3 - - - - - True - 25x15 - True - 0 - True - radio_18 - - - - 3 - 4 - - - - - False - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - GTK_BUTTONBOX_END - - - True - gtk-cancel - True - 0 - - - - - - True - gtk-ok - True - 1 - - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/plugins/TorrentPeers/tab_peers.py b/plugins/TorrentPeers/tab_peers.py deleted file mode 100644 index d181aaa70..000000000 --- a/plugins/TorrentPeers/tab_peers.py +++ /dev/null @@ -1,171 +0,0 @@ -# -*- coding: utf-8 -*- -# -# tab_peers.py -# -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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 itertools import izip -import deluge -from deluge import dgtk -from deluge import common -import gobject -import gtk -class PeersTabManager(object): - def __init__(self, peer_view, manager): - self.peer_view = peer_view - self.manager = manager - self.peer_unique_id = None - self.config_file = deluge.common.CONFIG_DIR + "/peers.conf" - self.config = deluge.pref.Preferences(self.config_file, False, - defaults={'ip_p_width': 120, - 'client_p_width' : 120, - 'percent_p_width': 90, - 'down_p_width': 150, - 'up_p_width': 115}) - try: - self.config.load() - except IOError: - # File does not exist - pass - # IP int, IP string, Client, Percent Complete, Down Speed, Up Speed - # IP int is for faster sorting - self.peer_store = gtk.ListStore(gobject.TYPE_UINT, gtk.gdk.Pixbuf, - str, str, float, int, int) - # Stores IP -> gtk.TreeIter's iter mapping for quick look up - # in update_torrent_info_widget - self.peer_store_dict = {} - self._cached_flags = {} - self.show_flags = None - self.flag_size = "" - - def clear_peer_store(self): - self.peer_store.clear() - self.peer_store_dict = {} - - def set_unique_id(self, unique_id): - self.peer_unique_id = unique_id - - def build_peers_view(self): - def percent(column, cell, model, iter, data): - percent = float(model.get_value(iter, data)) - percent_str = "%.2f%%"%percent - cell.set_property("text", percent_str) - - self.peer_view.set_model(self.peer_store) - - # self.ip_column is used in self.ip_column_queue_resize() method - self.ip_column = dgtk.add_texticon_column(self.peer_view, - _("IP Address"), 1, 2, width=140) - self.ip_column.set_sort_column_id(0) - client = dgtk.add_text_column(self.peer_view, _("Client"), 3, width=120) - percent = dgtk.add_func_column(self.peer_view, _("Percent Complete"), - percent, 4, width=150) - down = dgtk.add_func_column(self.peer_view, _("Down Speed"), - dgtk.cell_data_speed, 5, width=115) - up = dgtk.add_func_column(self.peer_view, _("Up Speed"), - dgtk.cell_data_speed, 6, width=115) - - def enable_flags(self): - self.show_flags = True - - def disable_flags(self): - self.show_flags = False - - def clear_flag_cache(self): - self._cached_flags = {} - - def set_flag_size(self, size): - self.flag_size = size - - def ip_column_queue_resize(self): - self.ip_column.queue_resize() - - def get_country_flag_image(self, country): - flag_image = None - if self.show_flags and country.isalpha(): - if country in self._cached_flags: - flag_image = self._cached_flags[country] - else: - try: - flag_path = "flags%s/%s.png" % (self.flag_size, - country.lower()) - flag_image = gtk.gdk.pixbuf_new_from_file( - common.get_pixmap(flag_path)) - except gobject.GError: - pass - - self._cached_flags[country] = flag_image - - return flag_image - - def update_peer_store(self): - new_peer_info = self.manager.get_torrent_peer_info(self.peer_unique_id) - new_ips = set() - - for peer in new_peer_info: - # Update peers already in peers list - if peer['ip'] in self.peer_store_dict: - iter = self.peer_store_dict[peer['ip']] - - dgtk.update_store(self.peer_store, iter, (1, 4, 5, 6), - (self.get_country_flag_image(peer["country"]), - round(peer["peer_has"], 2), - peer["download_speed"], - peer["upload_speed"])) - - if peer['client'] != "": - new_ips.add(peer['ip']) - - # Add new peers - if peer['ip'] not in self.peer_store_dict: - # convert IP to int for sorting purposes - ip_int = sum([int(byte) << shift - for byte, shift in - izip(peer["ip"].split("."), - (24, 16, 8, 0))]) - - client = peer["client"] - try: - client = client.decode('utf-8') - except UnicodeDecodeError: - # Fallback to latin-1 in case peer's client - # doesn't use utf-8. utorrent < 1.7 for example - client = client.decode('latin-1') - - iter = self.peer_store.append([ip_int, - self.get_country_flag_image(peer["country"]), - peer["ip"], client, round(peer["peer_has"], 2), - peer["download_speed"], peer["upload_speed"]]) - - self.peer_store_dict[peer['ip']] = iter - - # Remove peers that no longer exist in new_ips - for ip in set(self.peer_store_dict.keys()).difference(new_ips): - self.peer_store.remove(self.peer_store_dict[ip]) - del self.peer_store_dict[ip] diff --git a/plugins/WebSeed/__init__.py b/plugins/WebSeed/__init__.py deleted file mode 100644 index 4cd73f645..000000000 --- a/plugins/WebSeed/__init__.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (C) 2007 - Marcos Pinto -# -# 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 2, 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 St, Fifth Floor, Boston, MA 02110-1301 USA. - -### Initialization ### - -plugin_name = "Web Seed" -plugin_author = "Marcos Pinto" -plugin_version = "0.1" -plugin_description = _("This plugin allows users to add web seeds to their \ -torrents") - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return webseedMenu(path, core, interface) - - -import deluge -import gtk -import os.path - -class webseedMenu: - - def __init__(self, path, core, interface): - print "Found Web Seed plugin..." - self.path = path - self.core = core - self.interface = interface - self.glade = gtk.glade.XML(os.path.join(path, "webseed.glade")) - self.dialog = self.glade.get_widget("dialog") - # Add menu item to torrent context menu - self.menuitem_image = gtk.Image() - self.menuitem_image.set_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_MENU) - - self.menuitem = gtk.ImageMenuItem(_("_Add Web Seed")) - self.menuitem.set_image(self.menuitem_image) - self.menuitem.connect("activate", self.webseed_clicked) - self.interface.torrent_menu.append(self.menuitem) - self.menuitem.show_all() - for torrent in self.core.get_queue(): - unique_ID = self.core.get_torrent_unique_id(torrent) - try: - if self.core.unique_IDs[unique_ID].webseed_urls: - for urls in self.core.unique_IDs[unique_ID].webseed_urls: - self.core.add_url_seed(unique_ID, urls) - except AttributeError: - pass - - def update(self): - pass - - def unload(self): - self.interface.torrent_menu.remove(self.menuitem) - - def webseed_clicked(self, widget): - self.unique_ID = self.interface.get_selected_torrent() - self.dialog.show() - response = self.dialog.run() - self.dialog.hide() - if response: - text = self.glade.get_widget("txt_url").get_text().strip() - if deluge.common.is_url(text): - self.core.add_url_seed(self.unique_ID, text) diff --git a/plugins/WebSeed/webseed.glade b/plugins/WebSeed/webseed.glade deleted file mode 100644 index f9e7349e6..000000000 --- a/plugins/WebSeed/webseed.glade +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - 5 - Add Web Seed - GTK_WIN_POS_CENTER_ALWAYS - 400 - 100 - GDK_WINDOW_TYPE_HINT_NORMAL - False - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - 2 - - - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - URL: - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - 1 - - - - - False - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK - GTK_BUTTONBOX_END - - - True - gtk-cancel - True - 0 - - - - - True - gtk-ok - True - 1 - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/plugins/WebUi/LICENSE b/plugins/WebUi/LICENSE deleted file mode 100644 index 4856598ea..000000000 --- a/plugins/WebUi/LICENSE +++ /dev/null @@ -1,350 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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 2 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. - - 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. diff --git a/plugins/WebUi/TODO b/plugins/WebUi/TODO deleted file mode 100644 index e0944ed43..000000000 --- a/plugins/WebUi/TODO +++ /dev/null @@ -1,20 +0,0 @@ -0.5.7 -SSL -torrent/add http-post for private sites -rename reannounce->update-tracker. -queued displays as seeding/downloading - - -0.5.7 advanced layout -fonts -fix auto-refresh-layout -buttons -hide 0.0 kbps like in gtk-ui -update-tracker. - -0.6 -prepare for cat: - filters on status (prepare for cat) - filters on tracker -categories -greasemonkey : private sites. \ No newline at end of file diff --git a/plugins/WebUi/__init__.py b/plugins/WebUi/__init__.py deleted file mode 100644 index 4c37f8c6a..000000000 --- a/plugins/WebUi/__init__.py +++ /dev/null @@ -1,289 +0,0 @@ -# -*- coding: utf-8 -*- -# -# -# Copyright (C) Martijn Voncken 2007 -# -# 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 2, 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 - -plugin_name = "Web User Interface" -plugin_author = "Martijn Voncken" -plugin_version = "rev." -plugin_description = """A Web based User Interface - -Firefox greasemonkey script: http://userscripts.org/scripts/show/12639 - -Remotely add a file: "curl -F torrent=@./test1.torrent -F pwd=deluge http://localhost:8112/remote/torrent/add" - -Advanced template is only tested on firefox and garanteed not to work in IE6 - -ssl keys are located in WebUi/ssl/ - -Other contributors: -*somedude : template enhancements. -*markybob : stability : synced with his changes in deluge-svn. -""" - -import deluge.common -try: - import deluge.pref - from deluge.dialogs import show_popup_warning - import webserver_common -except ImportError: - print 'WebUi:not imported as a plugin' - - - -try: - from dbus_interface import get_dbus_manager -except: - print 'error importing dbus-interface!' - pass #for unit-test. - -import time - -import gtk -import os -from subprocess import Popen -from md5 import md5 -from threading import Thread -import random -random.seed() - -plugin_version += open(os.path.join(os.path.dirname(__file__),'revno')).read() -plugin_description += ( - open(os.path.join(os.path.dirname(__file__),'version')).read()) - -def deluge_init(deluge_path): - global path - path = deluge_path - -def enable(core, interface): - global path - return plugin_WebUi(path, core, interface) - -class plugin_WebUi(object): - def __init__(self, path, deluge_core, deluge_interface): - self.path = path - self.core = deluge_core - self.interface = deluge_interface - self.proc = None - self.web_server = None - if not deluge.common.windows_check(): - import commands - status = commands.getstatusoutput( - 'ps x |grep -v grep |grep run_webserver') - if status[0] == 0: - os.kill(int(status[1].split()[0]), 9) - time.sleep(1) #safe time to wait for kill to finish. - self.config_file = deluge.common.CONFIG_DIR + "/webui.conf" - self.config = deluge.pref.Preferences(self.config_file, False) - try: - self.config.load() - except IOError: - # File does not exist - pass - - if not self.config.get('port'): #ugly way to detect new config file. - #set default values: - self.config.set("port", 8112) - self.config.set("button_style", 2) - self.config.set("auto_refresh", False) - self.config.set("auto_refresh_secs", 4) - self.config.set("template", "advanced") - self.config.save(self.config_file) - - if not self.config.get("pwd_salt"): - self.config.set("pwd_salt", "invalid") - self.config.set("pwd_md5", "invalid") - - if self.config.get("cache_templates") == None: - self.config.set("cache_templates", True) - - if deluge.common.windows_check(): - self.config.set("run_in_thread", True) - else: - self.config.set("run_in_thread", False) - - if self.config.get("use_https") == None: - self.config.set("use_https", False) - - self.dbus_manager = get_dbus_manager(deluge_core, deluge_interface, - self.config, self.config_file) - - self.start_server() - - def unload(self): - print 'WebUI:unload..' - self.kill_server() - - def update(self): - pass - - ## This will be only called if your plugin is configurable - def configure(self,parent_dialog): - d = ConfigDialog(self.config, self, parent_dialog) - if d.run() == gtk.RESPONSE_OK: - d.save_config() - d.destroy() - - def start_server(self): - self.kill_server() - - if self.config.get("run_in_thread"): - print 'Start Webui(inside gtk)..' - webserver_common.init_gtk_05() #reload changed config. - from deluge_webserver import WebServer #only import in threaded mode - - - self.web_server = WebServer() - self.web_server.start_gtk() - - else: - print 'Start Webui(in process)..' - server_bin = os.path.dirname(__file__) + '/run_webserver' - self.proc = Popen((server_bin,'env=0.5')) - - def kill_server(self): - if self.web_server: - print "webserver: stop" - self.web_server.stop_gtk() - self.web_server = None - if self.proc: - print "webserver: kill %i" % self.proc.pid - os.system("kill -9 %i" % self.proc.pid) - time.sleep(1) #safe time to wait for kill to finish. - self.proc = None - - def __del__(self): - self.kill_server() - -class ConfigDialog(gtk.Dialog): - """ - sorry, can't get used to gui builders. - from what I read glade is better, but i dont want to invest time in them. - """ - def __init__(self, config, plugin, parent): - print "Found WebUI plugin..." - gtk.Dialog.__init__(self ,parent=parent) - self.config = config - self.plugin = plugin - self.vb = gtk.VBox() - self.set_title(_("WebUi Config")) - - template_path = os.path.join(os.path.dirname(__file__), 'templates') - self.templates = [dirname for dirname - in os.listdir(template_path) - if os.path.isdir(os.path.join(template_path, dirname)) - and not dirname.startswith('.')] - - self.port = self.add_widget(_('Port Number'), gtk.SpinButton()) - self.pwd1 = self.add_widget(_('New Password'), gtk.Entry()) - self.pwd2 = self.add_widget(_('New Password(confirm)'), gtk.Entry()) - self.template = self.add_widget(_('Template'), gtk.combo_box_new_text()) - self.button_style = self.add_widget(_('Button Style'), - gtk.combo_box_new_text()) - self.cache_templates = self.add_widget(_('Cache Templates'), - gtk.CheckButton()) - self.use_https = self.add_widget(_('https://'), - gtk.CheckButton()) - - #self.share_downloads = self.add_widget(_('Share Download Directory'), - # gtk.CheckButton()) - - self.port.set_range(80, 65536) - self.port.set_increments(1, 10) - self.pwd1.set_visibility(False) - self.pwd2.set_visibility(False) - - for item in self.templates: - self.template.append_text(item) - - if not self.config.get("template") in self.templates: - self.config.set("template","deluge") - - for item in [_('Text and image'), _('Image Only'), _('Text Only')]: - self.button_style.append_text(item) - if self.config.get("button_style") == None: - self.config.set("button_style", 2) - - self.port.set_value(int(self.config.get("port"))) - self.template.set_active( - self.templates.index(self.config.get("template"))) - self.button_style.set_active(self.config.get("button_style")) - #self.share_downloads.set_active( - # bool(self.config.get("share_downloads"))) - - self.cache_templates.set_active(self.config.get("cache_templates")) - self.use_https.set_active(self.config.get("use_https")) - - self.vbox.pack_start(self.vb, True, True, 0) - self.vb.show_all() - - self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL - ,gtk.STOCK_OK, gtk.RESPONSE_OK) - - #disable https if pyopenssl is not installed - try: - import OpenSSL - except: - self.use_https.set_sensitive(False) - - - def add_widget(self,label,w=None): - hb = gtk.HBox() - lbl = gtk.Label(label) - lbl.set_size_request(200,20) - hb.pack_start(lbl,False,False, 0) - hb.pack_start(w,True,True, 0) - - self.vb.pack_start(hb,False,False, 0) - return w - self.add_buttons(dgtk.STOCK_CLOSE, dgtk.RESPONSE_CLOSE) - - def save_config(self): - if self.pwd1.get_text() > '': - if self.pwd1.get_text() <> self.pwd2.get_text(): - show_popup_warning(self,_("Confirmed Password <> New Password\n" - + "Password was not changed")) - else: - sm = md5() - sm.update(str(random.getrandbits(5000))) - salt = sm.digest() - self.config.set("pwd_salt", salt) - # - m = md5() - m.update(salt) - m.update(unicode(self.pwd1.get_text())) - self.config.set("pwd_md5", m.digest()) - - self.config.set("port", int(self.port.get_value())) - self.config.set("template", self.template.get_active_text()) - self.config.set("button_style", self.button_style.get_active()) - self.config.set("cache_templates", self.cache_templates.get_active()) - self.config.set("use_https", self.use_https.get_active()) - #self.config.set("share_downloads", self.share_downloads.get_active()) - self.config.save(self.plugin.config_file) - self.plugin.start_server() #restarts server diff --git a/plugins/WebUi/dbus_interface.py b/plugins/WebUi/dbus_interface.py deleted file mode 100644 index cc70d42fe..000000000 --- a/plugins/WebUi/dbus_interface.py +++ /dev/null @@ -1,284 +0,0 @@ -# -*- coding: utf-8 -*- -# Dbus Ipc for experimental web interface -# -# dbus_interface.py -# -# Copyright (C) Martijn Voncken 2007 -# Contains copy and pasted code from other parts of deluge,see deluge AUTHORS -# -# 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 2, 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. - -import os -import gtk -import dbus -import deluge.common as common -from lib.pythonize import pythonize -import base64 -import random -random.seed() - -dbus_interface="org.deluge_torrent.dbusplugin" -dbus_service="/org/deluge_torrent/DelugeDbusPlugin" - -dbus_manager = None -def get_dbus_manager(*args): - #another way to make a singleton. - global dbus_manager - if not dbus_manager: - dbus_manager = DbusManager(*args) - return dbus_manager - -class DbusManager(dbus.service.Object): - def __init__(self, core, interface,config,config_file): - self.core = core - self.interface = interface - self.config = config - self.config_file = config_file - self.bus = dbus.SessionBus() - bus_name = dbus.service.BusName(dbus_interface,bus=self.bus) - dbus.service.Object.__init__(self, bus_name,dbus_service) - - # - #todo : add: get_interface_version in=i,get_config_value in=s out=s - # - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="",out_signature="as") - def get_session_state(self): - """Returns a list of torrent_ids in the session. - same as 0.6, but returns type "as" instead of a pickle - """ - torrent_list = [str(key) for key in self.core.unique_IDs] - return torrent_list - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="sas",out_signature="a{sv}") - def get_torrent_status(self, torrent_id, keys): - """return torrent metadata of a single torrent as a dict - 0.6 returns a pickle, this returns a dbus-type. - +added some more values to the dict - """ - - torrent_id = int(torrent_id) - # Convert the array of strings to a python list of strings - nkeys = [str(key) for key in keys] - - state = self.core.get_torrent_state(torrent_id) - torrent = self.core.unique_IDs[torrent_id] - - status = { - "name": state["name"].decode('utf-8','ignore'), - "total_size": state["total_size"], - "num_pieces": state["num_pieces"], - "state": state['state'], - "user_paused": self.core.is_user_paused(torrent_id), - "paused":state['is_paused'], - "progress": int(state["progress"] * 100), - "next_announce": state["next_announce"], - "total_payload_download":state["total_payload_download"], - "total_payload_upload": state["total_payload_upload"], - "download_payload_rate": state["download_rate"], - "upload_payload_rate": state["upload_rate"], - "num_peers": state["num_peers"], - "num_seeds": state["num_seeds"], - "total_wanted": state["total_wanted"], - "eta": common.estimate_eta(state), - "ratio": self.interface.manager.calc_ratio(torrent_id,state), - #non 0.6 values follow here: - "tracker_status": state.get("tracker_status","?").decode('utf-8','ignore'), - "uploaded_memory": torrent.uploaded_memory, - "tracker":state["tracker"].decode('utf-8','ignore') - } - #more non 0.6 values - for key in ["total_seeds", "total_peers","is_seed", "total_done", - "total_download", "total_upload" - #, "download_rate","upload_rate" - , "num_files", "piece_length", "distributed_copies" - ,"next_announce","queue_pos"]: - status[key] = state[key] - - #print 'all_keys:',sorted(status.keys()) - - status_subset = {} - for key in keys: - if key in status: - status_subset[key] = status[key] - else: - print 'mbus error,no key named:', key - return status_subset - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="as",out_signature="") - def pause_torrent(self, torrents): - """same as 0.6 interface""" - for torrent_id in torrents: - torrent_id = int(torrent_id) - self.core.set_user_pause(torrent_id, True) - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="as", out_signature="") - def resume_torrent(self, torrents): - """same as 0.6 interface""" - for torrent_id in torrents: - torrent_id = int(torrent_id) - self.core.set_user_pause(torrent_id, False) - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="as", out_signature="") - def force_reannounce(self, torrents): - """same as 0.6 interface""" - for torrent_id in torrents: - torrent_id = int(torrent_id) - self.core.update_tracker(torrent_id) - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="asbb", out_signature="") - def remove_torrent(self, torrent_ids, data_also, torrent_also): - """remove a torrent,and optionally data and torrent - additions compared to 0.6 interface: (data_also, torrent_also) - """ - for torrent_id in torrent_ids: - torrent_id = int(torrent_id) - self.core.remove_torrent(torrent_id, bool(data_also) - ,bool( torrent_also)) - - #this should not be needed: - gtk.gdk.threads_enter() - try: - self.interface.torrent_model_remove(torrent_id) - except: - pass - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="s", out_signature="b") - def add_torrent_url(self, url): - filename = fetch_url(url) - self._add_torrent(filename) - return True - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="s", out_signature="b") - def queue_up(self, torrent_id): - self.core.queue_up(int(torrent_id)) - return True - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="s", out_signature="b") - def queue_down(self, torrent_id): - self.core.queue_down(int(torrent_id)) - return True - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="ss", out_signature="b") - def add_torrent_filecontent(self, name, filecontent_b64): - """not available in deluge 0.6 interface""" - #name = fillename without directory - name = name.replace('\\','/') - name = 'deluge_' + str(random.random()) + '_' + name.split('/')[-1] - filename = os.path.join(self.core.config.get("default_download_path"), name) - - filecontent = base64.b64decode(filecontent_b64) - f = open(filename,"wb") #no with statement, that's py 2.5+ - f.write(filecontent) - f.close() - print 'write:',filename - self._add_torrent(filename) - return True - - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="", out_signature="a{sv}") - def get_config(self): - return self.core.config.mapping - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="s", out_signature="v") - def get_config_value(self,key): - return self.core.config.mapping[pythonize(key)] #ugly! - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="a{sv}", out_signature="") - def set_config(self, config): - """Set the config with values from dictionary""" - config = deluge.common.pythonize(config) - # Load all the values into the configuration - for key in self.core.config.keys(): - self.core.config[key] = config[key] - self.core.apply_prefs() - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="", out_signature="v") - def get_download_rate(self): - return self.core.get_state()['download_rate'] - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="", out_signature="v") - def get_upload_rate(self): - return self.core.get_state()['upload_rate'] - - @dbus.service.method(dbus_interface=dbus_interface, - in_signature="", out_signature="v") - def get_num_connections(self): - core_state = self.core.get_state() - return core_state['num_connections'] - - #internal - def _add_torrent(self, filename): - filename = unicode(filename) - target = self.core.config.get("default_download_path") - - torrent_id = self.core.add_torrent(filename, target, - self.interface.config.get("use_compact_storage")) - - #update gtk-ui This should not be needed!! - gtk.gdk.threads_enter() - try: - self.interface.torrent_model_append(torrent_id) - except: - pass - #finally is 2.5 only! - gtk.gdk.threads_leave() - - return True - -def fetch_url(url): - import urllib - - try: - filename, headers = urllib.urlretrieve(url) - except IOError: - raise Exception( "Network error while trying to fetch torrent from %s" - % url) - else: - if (filename.endswith(".torrent") or - headers["content-type"]=="application/x-bittorrent"): - return filename - else: - raise Exception("URL doesn't appear to be a valid torrent file:%s" - % url) - - return None diff --git a/plugins/WebUi/deluge_webserver.py b/plugins/WebUi/deluge_webserver.py deleted file mode 100644 index b5cc654aa..000000000 --- a/plugins/WebUi/deluge_webserver.py +++ /dev/null @@ -1,379 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# deluge_webserver.py -# -# Copyright (C) Martijn Voncken 2007 -# -# 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 2, 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. - -import webserver_common as ws -from webserver_framework import * - -import lib.webpy022 as web -from lib.webpy022.http import seeother, url - -import base64 -from operator import attrgetter -import os - -#routing: -urls = ( - "/login", "login", - "/index", "index", - "/torrent/info/(.*)", "torrent_info", - "/torrent/info_inner/(.*)", "torrent_info_inner", - "/torrent/stop/(.*)", "torrent_stop", - "/torrent/start/(.*)", "torrent_start", - "/torrent/reannounce/(.*)", "torrent_reannounce", - "/torrent/add(.*)", "torrent_add", - "/torrent/delete/(.*)", "torrent_delete", - "/torrent/queue/up/(.*)", "torrent_queue_up", - "/torrent/queue/down/(.*)", "torrent_queue_down", - "/pause_all", "pause_all", - "/resume_all", "resume_all", - "/refresh/set", "refresh_set", - "/refresh/(.*)", "refresh", - "/config", "config_", - "/home", "home", - "/about", "about", - "/logout", "logout", - #remote-api: - "/remote/torrent/add(.*)", "remote_torrent_add", - #static: - "/static/(.*)", "static", - "/template/static/(.*)", "template_static", - #"/downloads/(.*)","downloads" disabled until it can handle large downloads - #default-pages - "/", "home", - "", "home" -) -#/routing - -#pages: -class login: - @deluge_page_noauth - def GET(self, name): - vars = web.input(error = None) - return ws.render.login(vars.error) - - def POST(self): - vars = web.input(pwd = None, redir = None) - - if check_pwd(vars.pwd): - #start new session - start_session() - do_redirect() - elif vars.redir: - seeother(url('/login', error=1, redir=vars.redir)) - else: - seeother('/login?error=1') - -class index: - "page containing the torrent list." - @deluge_page - @auto_refreshed - def GET(self, name): - vars = web.input(sort=None, order=None ,filter=None , category=None) - torrent_list = [get_torrent_status(torrent_id) - for torrent_id in ws.proxy.get_session_state()] - all_torrents = torrent_list[:] - - #filter-state - if vars.filter: - torrent_list = filter_torrent_state(torrent_list, vars.filter) - setcookie("filter", vars.filter) - else: - setcookie("filter", "") - - #filter-cat - if vars.category: - torrent_list = [t for t in torrent_list if t.category == vars.category] - setcookie("category", vars.category) - else: - setcookie("category", "") - - #sorting: - if vars.sort: - torrent_list.sort(key=attrgetter(vars.sort)) - if vars.order == 'up': - torrent_list = reversed(torrent_list) - - setcookie("order", vars.order) - setcookie("sort", vars.sort) - - return ws.render.index(torrent_list, all_torrents) - -class torrent_info: - @deluge_page - @auto_refreshed - def GET(self, name): - torrent_id = name.split(',')[0] - return ws.render.torrent_info(get_torrent_status(torrent_id)) - -class torrent_info_inner: - @deluge_page - def GET(self, torrent_ids): - torrent_ids = torrent_ids.split(',') - info = get_torrent_status(torrent_ids[0]) - if len(torrent_ids) > 1: - #todo : hmm, lots of manual stuff here :( - pass - - - return ws.render.torrent_info_inner(info) - -class torrent_start: - @check_session - def POST(self, name): - torrent_ids = name.split(',') - ws.proxy.resume_torrent(torrent_ids) - do_redirect() - -class torrent_stop: - @check_session - def POST(self, name): - torrent_ids = name.split(',') - ws.proxy.pause_torrent(torrent_ids) - do_redirect() - -class torrent_reannounce: - @check_session - def POST(self, torrent_id): - ws.proxy.force_reannounce([torrent_id]) - do_redirect() - -class torrent_add: - @deluge_page - def GET(self, name): - return ws.render.torrent_add() - - @check_session - def POST(self, name): - """ - allows: - *posting of url - *posting file-upload - *posting of data as string(for greasemonkey-private) - """ - - vars = web.input(url = None, torrent = {}) - - torrent_name = None - torrent_data = None - if vars.torrent.filename: - torrent_name = vars.torrent.filename - torrent_data = vars.torrent.file.read() - - if vars.url and torrent_name: - error_page(_("Choose an url or a torrent, not both.")) - if vars.url: - ws.proxy.add_torrent_url(vars.url) - do_redirect() - elif torrent_name: - data_b64 = base64.b64encode(torrent_data) - #b64 because of strange bug-reports related to binary data - ws.proxy.add_torrent_filecontent(vars.torrent.filename, data_b64) - do_redirect() - else: - error_page(_("no data.")) - -class remote_torrent_add: - """ - For use in remote scripts etc. - curl ->POST pwd and torrent as file - greasemonkey: POST pwd torrent_name and data_b64 - """ - @remote - def POST(self, name): - vars = web.input(pwd = None, torrent = {}, - data_b64 = None , torrent_name= None) - - if not check_pwd(vars.pwd): - return 'error:wrong password' - - if vars.data_b64: #b64 post (greasemonkey) - data_b64 = unicode(vars.data_b64) - torrent_name = vars.torrent_name - else: #file-post (curl) - data_b64 = base64.b64encode(vars.torrent.file.read()) - torrent_name = vars.torrent.filename - - ws.proxy.add_torrent_filecontent(torrent_name, data_b64) - return 'ok' - -class torrent_delete: - @deluge_page - def GET(self, name): - torrent_ids = name.split(',') - torrent_list = [get_torrent_status(id) for id in torrent_ids] - return ws.render.torrent_delete(name, torrent_list) - - @check_session - def POST(self, name): - torrent_ids = name.split(',') - vars = web.input(data_also = None, torrent_also = None) - data_also = bool(vars.data_also) - torrent_also = bool(vars.torrent_also) - ws.proxy.remove_torrent(torrent_ids, data_also, torrent_also) - do_redirect() - -class torrent_queue_up: - @check_session - def POST(self, name): - #a bit too verbose.. - torrent_ids = name.split(',') - torrents = [get_torrent_status(id) for id in torrent_ids] - torrents.sort(lambda x, y : x.queue_pos - y.queue_pos) - torrent_ids = [t.id for t in torrents] - for torrent_id in torrent_ids: - ws.proxy.queue_up(torrent_id) - do_redirect() - -class torrent_queue_down: - @check_session - def POST(self, name): - #a bit too verbose.. - torrent_ids = name.split(',') - torrents = [get_torrent_status(id) for id in torrent_ids] - torrents.sort(lambda x, y : x.queue_pos - y.queue_pos) - torrent_ids = [t.id for t in torrents] - for torrent_id in reversed(torrent_ids): - ws.proxy.queue_down(torrent_id) - do_redirect() - -class pause_all: - @check_session - def POST(self, name): - ws.proxy.pause_torrent(ws.proxy.get_session_state()) - do_redirect() - -class resume_all: - @check_session - def POST(self, name): - ws.proxy.resume_torrent(ws.proxy.get_session_state()) - do_redirect() - -class refresh: - @check_session - def POST(self, name): - auto_refresh = {'off': '0', 'on': '1'}[name] - setcookie('auto_refresh', auto_refresh) - if not getcookie('auto_refresh_secs'): - setcookie('auto_refresh_secs', 10) - do_redirect() - -class refresh_set: - @deluge_page - def GET(self, name): - return ws.render.refresh_form() - - @check_session - def POST(self, name): - vars = web.input(refresh = 0) - refresh = int(vars.refresh) - if refresh > 0: - setcookie('auto_refresh', '1') - setcookie('auto_refresh_secs', str(refresh)) - do_redirect() - else: - error_page(_('refresh must be > 0')) - -class config_: #namespace clash? - """core config - TODO:good validation. - """ - """ - SOMEHOW ONLY BREAKS 0.6 ?? - cfg_form = web.form.Form( - web.form.Dropdown('max_download', ws.SPEED_VALUES, - description=_('Download Speed Limit'), - post='%s Kib/sec' % ws.proxy.get_config_value('max_download_speed') - ) - ,web.form.Dropdown('max_upload', ws.SPEED_VALUES, - description=_('Upload Speed Limit'), - post='%s Kib/sec' % ws.proxy.get_config_value('max_upload_speed') - ) - ) - - @deluge_page - def GET(self, name): - return ws.render.config(self.cfg_form()) - - def POST(self, name): - vars = web.input(max_download=None, max_upload=None) - - #self.config.set("max_download_speed", float(str_bwdown)) - raise NotImplementedError('todo') - """ - -class home: - @check_session - def GET(self, name): - do_redirect() - -class about: - @deluge_page_noauth - def GET(self, name): - return ws.render.about() - -class logout: - @check_session - def POST(self, name): - end_session() - seeother('/login') - -class static(static_handler): - base_dir = os.path.join(os.path.dirname(__file__), 'static') - -class template_static(static_handler): - def get_base_dir(self): - return os.path.join(os.path.dirname(__file__), - 'templates/%s/static' % ws.config.get('template')) - -class downloads(static_handler): - def GET(self, name): - self.base_dir = ws.proxy.get_config_value('default_download_path') - if not ws.config.get('share_downloads'): - raise Exception('Access to downloads is forbidden.') - return static_handler.GET(self, name) -#/pages - - -def WebServer(): - return create_webserver(urls, globals()) - - -def run(): - server = WebServer() - try: - server.start() - except KeyboardInterrupt: - server.stop() - -if __name__ == "__main__": - run() diff --git a/plugins/WebUi/lib/gtk_cherrypy_wsgiserver.py b/plugins/WebUi/lib/gtk_cherrypy_wsgiserver.py deleted file mode 100644 index ce55b3fa7..000000000 --- a/plugins/WebUi/lib/gtk_cherrypy_wsgiserver.py +++ /dev/null @@ -1,1077 +0,0 @@ -""" -mvoncken: -Modified this to integrate into the gtk main-loop. -*split start() into start_common(),start,start_gtk(),start() -*add stop_gtk() -*add CherryPy license in comment ----- -Copyright (c) 2004-2007, CherryPy Team (team@cherrypy.org) -All rights reserved. - -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 CherryPy Team 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. - -A high-speed, production ready, thread pooled, generic WSGI server. - -Simplest example on how to use this module directly -(without using CherryPy's application machinery): - - from cherrypy import wsgiserver - - def my_crazy_app(environ, start_response): - status = '200 OK' - response_headers = [('Content-type','text/plain')] - start_response(status, response_headers) - return ['Hello world!\n'] - - # Here we set our application to the script_name '/' - wsgi_apps = [('/', my_crazy_app)] - - server = wsgiserver.CherryPyWSGIServer(('localhost', 8070), wsgi_apps, - server_name='localhost') - - # Want SSL support? Just set these attributes - # server.ssl_certificate = - # server.ssl_private_key = - - if __name__ == '__main__': - try: - server.start() - except KeyboardInterrupt: - server.stop() - -This won't call the CherryPy engine (application side) at all, only the -WSGI server, which is independant from the rest of CherryPy. Don't -let the name "CherryPyWSGIServer" throw you; the name merely reflects -its origin, not it's coupling. - -The CherryPy WSGI server can serve as many WSGI applications -as you want in one instance: - - wsgi_apps = [('/', my_crazy_app), ('/blog', my_blog_app)] - -""" -import base64 -import Queue -import os -import re -quoted_slash = re.compile("(?i)%2F") -import rfc822 -import socket -try: - import cStringIO as StringIO -except ImportError: - import StringIO -import sys -import threading -import time -import traceback -from urllib import unquote -from urlparse import urlparse -try: - import gobject -except ImportError: - pass - -try: - from OpenSSL import SSL - from OpenSSL import crypto -except ImportError: - SSL = None - -import errno -socket_errors_to_ignore = [] -# Not all of these names will be defined for every platform. -for _ in ("EPIPE", "ETIMEDOUT", "ECONNREFUSED", "ECONNRESET", - "EHOSTDOWN", "EHOSTUNREACH", - "WSAECONNABORTED", "WSAECONNREFUSED", "WSAECONNRESET", - "WSAENETRESET", "WSAETIMEDOUT"): - if _ in dir(errno): - socket_errors_to_ignore.append(getattr(errno, _)) -# de-dupe the list -socket_errors_to_ignore = dict.fromkeys(socket_errors_to_ignore).keys() -socket_errors_to_ignore.append("timed out") - -comma_separated_headers = ['ACCEPT', 'ACCEPT-CHARSET', 'ACCEPT-ENCODING', - 'ACCEPT-LANGUAGE', 'ACCEPT-RANGES', 'ALLOW', 'CACHE-CONTROL', - 'CONNECTION', 'CONTENT-ENCODING', 'CONTENT-LANGUAGE', 'EXPECT', - 'IF-MATCH', 'IF-NONE-MATCH', 'PRAGMA', 'PROXY-AUTHENTICATE', 'TE', - 'TRAILER', 'TRANSFER-ENCODING', 'UPGRADE', 'VARY', 'VIA', 'WARNING', - 'WWW-AUTHENTICATE'] - -class HTTPRequest(object): - """An HTTP Request (and response). - - A single HTTP connection may consist of multiple request/response pairs. - - connection: the HTTP Connection object which spawned this request. - rfile: the 'read' fileobject from the connection's socket - ready: when True, the request has been parsed and is ready to begin - generating the response. When False, signals the calling Connection - that the response should not be generated and the connection should - close. - close_connection: signals the calling Connection that the request - should close. This does not imply an error! The client and/or - server may each request that the connection be closed. - chunked_write: if True, output will be encoded with the "chunked" - transfer-coding. This value is set automatically inside - send_headers. - """ - - def __init__(self, connection): - self.connection = connection - self.rfile = self.connection.rfile - self.sendall = self.connection.sendall - self.environ = connection.environ.copy() - - self.ready = False - self.started_response = False - self.status = "" - self.outheaders = [] - self.sent_headers = False - self.close_connection = False - self.chunked_write = False - - def parse_request(self): - """Parse the next HTTP request start-line and message-headers.""" - # HTTP/1.1 connections are persistent by default. If a client - # requests a page, then idles (leaves the connection open), - # then rfile.readline() will raise socket.error("timed out"). - # Note that it does this based on the value given to settimeout(), - # and doesn't need the client to request or acknowledge the close - # (although your TCP stack might suffer for it: cf Apache's history - # with FIN_WAIT_2). - request_line = self.rfile.readline() - if not request_line: - # Force self.ready = False so the connection will close. - self.ready = False - return - - if request_line == "\r\n": - # RFC 2616 sec 4.1: "...if the server is reading the protocol - # stream at the beginning of a message and receives a CRLF - # first, it should ignore the CRLF." - # But only ignore one leading line! else we enable a DoS. - request_line = self.rfile.readline() - if not request_line: - self.ready = False - return - - server = self.connection.server - environ = self.environ - environ["SERVER_SOFTWARE"] = "%s WSGI Server" % server.version - - method, path, req_protocol = request_line.strip().split(" ", 2) - environ["REQUEST_METHOD"] = method - - # path may be an abs_path (including "http://host.domain.tld"); - scheme, location, path, params, qs, frag = urlparse(path) - - if frag: - self.simple_response("400 Bad Request", - "Illegal #fragment in Request-URI.") - return - - if scheme: - environ["wsgi.url_scheme"] = scheme - if params: - path = path + ";" + params - - # Unquote the path+params (e.g. "/this%20path" -> "this path"). - # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 - # - # But note that "...a URI must be separated into its components - # before the escaped characters within those components can be - # safely decoded." http://www.ietf.org/rfc/rfc2396.txt, sec 2.4.2 - atoms = [unquote(x) for x in quoted_slash.split(path)] - path = "%2F".join(atoms) - - if path == "*": - # This means, of course, that the last wsgi_app (shortest path) - # will always handle a URI of "*". - environ["SCRIPT_NAME"] = "" - environ["PATH_INFO"] = "*" - self.wsgi_app = server.mount_points[-1][1] - else: - for mount_point, wsgi_app in server.mount_points: - # The mount_points list should be sorted by length, descending. - if path.startswith(mount_point + "/") or path == mount_point: - environ["SCRIPT_NAME"] = mount_point - environ["PATH_INFO"] = path[len(mount_point):] - self.wsgi_app = wsgi_app - break - else: - self.simple_response("404 Not Found") - return - - # Note that, like wsgiref and most other WSGI servers, - # we unquote the path but not the query string. - environ["QUERY_STRING"] = qs - - # Compare request and server HTTP protocol versions, in case our - # server does not support the requested protocol. Limit our output - # to min(req, server). We want the following output: - # request server actual written supported response - # protocol protocol response protocol feature set - # a 1.0 1.0 1.0 1.0 - # b 1.0 1.1 1.1 1.0 - # c 1.1 1.0 1.0 1.0 - # d 1.1 1.1 1.1 1.1 - # Notice that, in (b), the response will be "HTTP/1.1" even though - # the client only understands 1.0. RFC 2616 10.5.6 says we should - # only return 505 if the _major_ version is different. - rp = int(req_protocol[5]), int(req_protocol[7]) - sp = int(server.protocol[5]), int(server.protocol[7]) - if sp[0] != rp[0]: - self.simple_response("505 HTTP Version Not Supported") - return - # Bah. "SERVER_PROTOCOL" is actually the REQUEST protocol. - environ["SERVER_PROTOCOL"] = req_protocol - # set a non-standard environ entry so the WSGI app can know what - # the *real* server protocol is (and what features to support). - # See http://www.faqs.org/rfcs/rfc2145.html. - environ["ACTUAL_SERVER_PROTOCOL"] = server.protocol - self.response_protocol = "HTTP/%s.%s" % min(rp, sp) - - # If the Request-URI was an absoluteURI, use its location atom. - if location: - environ["SERVER_NAME"] = location - - # then all the http headers - try: - self.read_headers() - except ValueError, ex: - self.simple_response("400 Bad Request", repr(ex.args)) - return - - creds = environ.get("HTTP_AUTHORIZATION", "").split(" ", 1) - environ["AUTH_TYPE"] = creds[0] - if creds[0].lower() == 'basic': - user, pw = base64.decodestring(creds[1]).split(":", 1) - environ["REMOTE_USER"] = user - - # Persistent connection support - if self.response_protocol == "HTTP/1.1": - if environ.get("HTTP_CONNECTION", "") == "close": - self.close_connection = True - else: - # HTTP/1.0 - if environ.get("HTTP_CONNECTION", "") != "Keep-Alive": - self.close_connection = True - - # Transfer-Encoding support - te = None - if self.response_protocol == "HTTP/1.1": - te = environ.get("HTTP_TRANSFER_ENCODING") - if te: - te = [x.strip().lower() for x in te.split(",") if x.strip()] - - read_chunked = False - - if te: - for enc in te: - if enc == "chunked": - read_chunked = True - else: - # Note that, even if we see "chunked", we must reject - # if there is an extension we don't recognize. - self.simple_response("501 Unimplemented") - self.close_connection = True - return - - if read_chunked: - if not self.decode_chunked(): - return - - # From PEP 333: - # "Servers and gateways that implement HTTP 1.1 must provide - # transparent support for HTTP 1.1's "expect/continue" mechanism. - # This may be done in any of several ways: - # 1. Respond to requests containing an Expect: 100-continue request - # with an immediate "100 Continue" response, and proceed normally. - # 2. Proceed with the request normally, but provide the application - # with a wsgi.input stream that will send the "100 Continue" - # response if/when the application first attempts to read from - # the input stream. The read request must then remain blocked - # until the client responds. - # 3. Wait until the client decides that the server does not support - # expect/continue, and sends the request body on its own. - # (This is suboptimal, and is not recommended.) - # - # We used to do 3, but are now doing 1. Maybe we'll do 2 someday, - # but it seems like it would be a big slowdown for such a rare case. - if environ.get("HTTP_EXPECT", "") == "100-continue": - self.simple_response(100) - - self.ready = True - - def read_headers(self): - """Read header lines from the incoming stream.""" - environ = self.environ - - while True: - line = self.rfile.readline() - if not line: - # No more data--illegal end of headers - raise ValueError("Illegal end of headers.") - - if line == '\r\n': - # Normal end of headers - break - - if line[0] in ' \t': - # It's a continuation line. - v = line.strip() - else: - k, v = line.split(":", 1) - k, v = k.strip().upper(), v.strip() - envname = "HTTP_" + k.replace("-", "_") - - if k in comma_separated_headers: - existing = environ.get(envname) - if existing: - v = ", ".join((existing, v)) - environ[envname] = v - - ct = environ.pop("HTTP_CONTENT_TYPE", None) - if ct: - environ["CONTENT_TYPE"] = ct - cl = environ.pop("HTTP_CONTENT_LENGTH", None) - if cl: - environ["CONTENT_LENGTH"] = cl - - def decode_chunked(self): - """Decode the 'chunked' transfer coding.""" - cl = 0 - data = StringIO.StringIO() - while True: - line = self.rfile.readline().strip().split(";", 1) - chunk_size = int(line.pop(0), 16) - if chunk_size <= 0: - break -## if line: chunk_extension = line[0] - cl += chunk_size - data.write(self.rfile.read(chunk_size)) - crlf = self.rfile.read(2) - if crlf != "\r\n": - self.simple_response("400 Bad Request", - "Bad chunked transfer coding " - "(expected '\\r\\n', got %r)" % crlf) - return - - # Grab any trailer headers - self.read_headers() - - data.seek(0) - self.environ["wsgi.input"] = data - self.environ["CONTENT_LENGTH"] = str(cl) or "" - return True - - def respond(self): - """Call the appropriate WSGI app and write its iterable output.""" - response = self.wsgi_app(self.environ, self.start_response) - try: - for chunk in response: - # "The start_response callable must not actually transmit - # the response headers. Instead, it must store them for the - # server or gateway to transmit only after the first - # iteration of the application return value that yields - # a NON-EMPTY string, or upon the application's first - # invocation of the write() callable." (PEP 333) - if chunk: - self.write(chunk) - finally: - if hasattr(response, "close"): - response.close() - if (self.ready and not self.sent_headers - and not self.connection.server.interrupt): - self.sent_headers = True - self.send_headers() - if self.chunked_write: - self.sendall("0\r\n\r\n") - - def simple_response(self, status, msg=""): - """Write a simple response back to the client.""" - status = str(status) - buf = ["%s %s\r\n" % (self.connection.server.protocol, status), - "Content-Length: %s\r\n" % len(msg)] - - if status[:3] == "413" and self.response_protocol == 'HTTP/1.1': - # Request Entity Too Large - self.close_connection = True - buf.append("Connection: close\r\n") - - buf.append("\r\n") - if msg: - buf.append(msg) - self.sendall("".join(buf)) - - def start_response(self, status, headers, exc_info = None): - """WSGI callable to begin the HTTP response.""" - if self.started_response: - if not exc_info: - raise AssertionError("WSGI start_response called a second " - "time with no exc_info.") - else: - try: - raise exc_info[0], exc_info[1], exc_info[2] - finally: - exc_info = None - self.started_response = True - self.status = status - self.outheaders.extend(headers) - return self.write - - def write(self, chunk): - """WSGI callable to write unbuffered data to the client. - - This method is also used internally by start_response (to write - data from the iterable returned by the WSGI application). - """ - if not self.started_response: - raise AssertionError("WSGI write called before start_response.") - - if not self.sent_headers: - self.sent_headers = True - self.send_headers() - - if self.chunked_write and chunk: - buf = [hex(len(chunk))[2:], "\r\n", chunk, "\r\n"] - self.sendall("".join(buf)) - else: - self.sendall(chunk) - - def send_headers(self): - """Assert, process, and send the HTTP response message-headers.""" - hkeys = [key.lower() for key, value in self.outheaders] - status = int(self.status[:3]) - - if status == 413: - # Request Entity Too Large. Close conn to avoid garbage. - self.close_connection = True - elif "content-length" not in hkeys: - # "All 1xx (informational), 204 (no content), - # and 304 (not modified) responses MUST NOT - # include a message-body." So no point chunking. - if status < 200 or status in (204, 205, 304): - pass - else: - if self.response_protocol == 'HTTP/1.1': - # Use the chunked transfer-coding - self.chunked_write = True - self.outheaders.append(("Transfer-Encoding", "chunked")) - else: - # Closing the conn is the only way to determine len. - self.close_connection = True - - if "connection" not in hkeys: - if self.response_protocol == 'HTTP/1.1': - if self.close_connection: - self.outheaders.append(("Connection", "close")) - else: - if not self.close_connection: - self.outheaders.append(("Connection", "Keep-Alive")) - - if "date" not in hkeys: - self.outheaders.append(("Date", rfc822.formatdate())) - - server = self.connection.server - - if "server" not in hkeys: - self.outheaders.append(("Server", server.version)) - - buf = [server.protocol, " ", self.status, "\r\n"] - try: - buf += [k + ": " + v + "\r\n" for k, v in self.outheaders] - except TypeError: - if not isinstance(k, str): - raise TypeError("WSGI response header key %r is not a string.") - if not isinstance(v, str): - raise TypeError("WSGI response header value %r is not a string.") - else: - raise - buf.append("\r\n") - self.sendall("".join(buf)) - - -class NoSSLError(Exception): - """Exception raised when a client speaks HTTP to an HTTPS socket.""" - pass - - -def _ssl_wrap_method(method, is_reader=False): - """Wrap the given method with SSL error-trapping. - - is_reader: if False (the default), EOF errors will be raised. - If True, EOF errors will return "" (to emulate normal sockets). - """ - def ssl_method_wrapper(self, *args, **kwargs): -## print (id(self), method, args, kwargs) - start = time.time() - while True: - try: - return method(self, *args, **kwargs) - except (SSL.WantReadError, SSL.WantWriteError): - # Sleep and try again. This is dangerous, because it means - # the rest of the stack has no way of differentiating - # between a "new handshake" error and "client dropped". - # Note this isn't an endless loop: there's a timeout below. - time.sleep(self.ssl_retry) - except SSL.SysCallError, e: - if is_reader and e.args == (-1, 'Unexpected EOF'): - return "" - - errno = e.args[0] - if is_reader and errno in socket_errors_to_ignore: - return "" - raise socket.error(errno) - except SSL.Error, e: - if is_reader and e.args == (-1, 'Unexpected EOF'): - return "" - - thirdarg = None - try: - thirdarg = e.args[0][0][2] - except IndexError: - pass - - if is_reader and thirdarg == 'ssl handshake failure': - return "" - if thirdarg == 'http request': - # The client is talking HTTP to an HTTPS server. - raise NoSSLError() - raise - if time.time() - start > self.ssl_timeout: - raise socket.timeout("timed out") - return ssl_method_wrapper - -class SSL_fileobject(socket._fileobject): - """Faux file object attached to a socket object.""" - - ssl_timeout = 3 - ssl_retry = .01 - - close = _ssl_wrap_method(socket._fileobject.close) - flush = _ssl_wrap_method(socket._fileobject.flush) - write = _ssl_wrap_method(socket._fileobject.write) - writelines = _ssl_wrap_method(socket._fileobject.writelines) - read = _ssl_wrap_method(socket._fileobject.read, is_reader=True) - readline = _ssl_wrap_method(socket._fileobject.readline, is_reader=True) - readlines = _ssl_wrap_method(socket._fileobject.readlines, is_reader=True) - - -class HTTPConnection(object): - """An HTTP connection (active socket). - - socket: the raw socket object (usually TCP) for this connection. - addr: the "bind address" for the remote end of the socket. - For IP sockets, this is a tuple of (REMOTE_ADDR, REMOTE_PORT). - For UNIX domain sockets, this will be a string. - server: the HTTP Server for this Connection. Usually, the server - object possesses a passive (server) socket which spawns multiple, - active (client) sockets, one for each connection. - - environ: a WSGI environ template. This will be copied for each request. - rfile: a fileobject for reading from the socket. - sendall: a function for writing (+ flush) to the socket. - """ - - rbufsize = -1 - RequestHandlerClass = HTTPRequest - environ = {"wsgi.version": (1, 0), - "wsgi.url_scheme": "http", - "wsgi.multithread": True, - "wsgi.multiprocess": False, - "wsgi.run_once": False, - "wsgi.errors": sys.stderr, - } - - def __init__(self, sock, addr, server): - self.socket = sock - self.addr = addr - self.server = server - - # Copy the class environ into self. - self.environ = self.environ.copy() - - if SSL and isinstance(sock, SSL.ConnectionType): - timeout = sock.gettimeout() - self.rfile = SSL_fileobject(sock, "r", self.rbufsize) - self.rfile.ssl_timeout = timeout - self.sendall = _ssl_wrap_method(sock.sendall) - self.environ["wsgi.url_scheme"] = "https" - self.environ["HTTPS"] = "on" - sslenv = getattr(server, "ssl_environ", None) - if sslenv: - self.environ.update(sslenv) - else: - self.rfile = sock.makefile("rb", self.rbufsize) - self.sendall = sock.sendall - - self.environ.update({"wsgi.input": self.rfile, - "SERVER_NAME": self.server.server_name, - }) - - if isinstance(self.server.bind_addr, basestring): - # AF_UNIX. This isn't really allowed by WSGI, which doesn't - # address unix domain sockets. But it's better than nothing. - self.environ["SERVER_PORT"] = "" - else: - self.environ["SERVER_PORT"] = str(self.server.bind_addr[1]) - # optional values - # Until we do DNS lookups, omit REMOTE_HOST - self.environ["REMOTE_ADDR"] = self.addr[0] - self.environ["REMOTE_PORT"] = str(self.addr[1]) - - def communicate(self): - """Read each request and respond appropriately.""" - try: - while True: - # (re)set req to None so that if something goes wrong in - # the RequestHandlerClass constructor, the error doesn't - # get written to the previous request. - req = None - req = self.RequestHandlerClass(self) - # This order of operations should guarantee correct pipelining. - req.parse_request() - if not req.ready: - return - req.respond() - if req.close_connection: - return - except socket.error, e: - errno = e.args[0] - if errno not in socket_errors_to_ignore: - if req: - req.simple_response("500 Internal Server Error", - format_exc()) - return - except (KeyboardInterrupt, SystemExit): - raise - except NoSSLError: - # Unwrap our sendall - req.sendall = self.socket._sock.sendall - req.simple_response("400 Bad Request", - "The client sent a plain HTTP request, but " - "this server only speaks HTTPS on this port.") - except: - if req: - req.simple_response("500 Internal Server Error", format_exc()) - - def close(self): - """Close the socket underlying this connection.""" - self.rfile.close() - self.socket.close() - - -def format_exc(limit=None): - """Like print_exc() but return a string. Backport for Python 2.3.""" - try: - etype, value, tb = sys.exc_info() - return ''.join(traceback.format_exception(etype, value, tb, limit)) - finally: - etype = value = tb = None - - -_SHUTDOWNREQUEST = None - -class WorkerThread(threading.Thread): - """Thread which continuously polls a Queue for Connection objects. - - server: the HTTP Server which spawned this thread, and which owns the - Queue and is placing active connections into it. - ready: a simple flag for the calling server to know when this thread - has begun polling the Queue. - - Due to the timing issues of polling a Queue, a WorkerThread does not - check its own 'ready' flag after it has started. To stop the thread, - it is necessary to stick a _SHUTDOWNREQUEST object onto the Queue - (one for each running WorkerThread). - """ - - def __init__(self, server): - self.ready = False - self.server = server - threading.Thread.__init__(self) - - def run(self): - try: - self.ready = True - while True: - conn = self.server.requests.get() - if conn is _SHUTDOWNREQUEST: - return - - try: - conn.communicate() - finally: - conn.close() - except (KeyboardInterrupt, SystemExit), exc: - self.server.interrupt = exc - - -class SSLConnection: - """A thread-safe wrapper for an SSL.Connection. - - *args: the arguments to create the wrapped SSL.Connection(*args). - """ - - def __init__(self, *args): - self._ssl_conn = SSL.Connection(*args) - self._lock = threading.RLock() - - for f in ('get_context', 'pending', 'send', 'write', 'recv', 'read', - 'renegotiate', 'bind', 'listen', 'connect', 'accept', - 'setblocking', 'fileno', 'shutdown', 'close', 'get_cipher_list', - 'getpeername', 'getsockname', 'getsockopt', 'setsockopt', - 'makefile', 'get_app_data', 'set_app_data', 'state_string', - 'sock_shutdown', 'get_peer_certificate', 'want_read', - 'want_write', 'set_connect_state', 'set_accept_state', - 'connect_ex', 'sendall', 'settimeout'): - exec """def %s(self, *args): - self._lock.acquire() - try: - return self._ssl_conn.%s(*args) - finally: - self._lock.release() -""" % (f, f) - - -class CherryPyWSGIServer(object): - """An HTTP server for WSGI. - - bind_addr: a (host, port) tuple if TCP sockets are desired; - for UNIX sockets, supply the filename as a string. - wsgi_app: the WSGI 'application callable'; multiple WSGI applications - may be passed as (script_name, callable) pairs. - numthreads: the number of worker threads to create (default 10). - server_name: the string to set for WSGI's SERVER_NAME environ entry. - Defaults to socket.gethostname(). - max: the maximum number of queued requests (defaults to -1 = no limit). - request_queue_size: the 'backlog' argument to socket.listen(); - specifies the maximum number of queued connections (default 5). - timeout: the timeout in seconds for accepted connections (default 10). - - protocol: the version string to write in the Status-Line of all - HTTP responses. For example, "HTTP/1.1" (the default). This - also limits the supported features used in the response. - - - SSL/HTTPS - --------- - The OpenSSL module must be importable for SSL functionality. - You can obtain it from http://pyopenssl.sourceforge.net/ - - ssl_certificate: the filename of the server SSL certificate. - ssl_privatekey: the filename of the server's private key file. - - If either of these is None (both are None by default), this server - will not use SSL. If both are given and are valid, they will be read - on server start and used in the SSL context for the listening socket. - """ - - protocol = "HTTP/1.1" - version = "CherryPy/3.0.2" - ready = False - _interrupt = None - ConnectionClass = HTTPConnection - - # Paths to certificate and private key files - ssl_certificate = None - ssl_private_key = None - - def __init__(self, bind_addr, wsgi_app, numthreads=10, server_name=None, - max=-1, request_queue_size=5, timeout=10): - self.requests = Queue.Queue(max) - - if callable(wsgi_app): - # We've been handed a single wsgi_app, in CP-2.1 style. - # Assume it's mounted at "". - self.mount_points = [("", wsgi_app)] - else: - # We've been handed a list of (mount_point, wsgi_app) tuples, - # so that the server can call different wsgi_apps, and also - # correctly set SCRIPT_NAME. - self.mount_points = wsgi_app - self.mount_points.sort() - self.mount_points.reverse() - - self.bind_addr = bind_addr - self.numthreads = numthreads or 1 - if not server_name: - server_name = socket.gethostname() - self.server_name = server_name - self.request_queue_size = request_queue_size - self._workerThreads = [] - self.gtk_idle_id = None - - self.timeout = timeout - - def start_common(self): - """Run the server forever.""" - # We don't have to trap KeyboardInterrupt or SystemExit here, - # because cherrpy.server already does so, calling self.stop() for us. - # If you're using this server with another framework, you should - # trap those exceptions in whatever code block calls start(). - self._interrupt = None - - # Select the appropriate socket - if isinstance(self.bind_addr, basestring): - # AF_UNIX socket - - # So we can reuse the socket... - try: os.unlink(self.bind_addr) - except: pass - - # So everyone can access the socket... - try: os.chmod(self.bind_addr, 0777) - except: pass - - info = [(socket.AF_UNIX, socket.SOCK_STREAM, 0, "", self.bind_addr)] - else: - # AF_INET or AF_INET6 socket - # Get the correct address family for our host (allows IPv6 addresses) - host, port = self.bind_addr - flags = 0 - if host == '': - # Despite the socket module docs, using '' does not - # allow AI_PASSIVE to work. Passing None instead - # returns '0.0.0.0' like we want. In other words: - # host AI_PASSIVE result - # '' Y 192.168.x.y - # '' N 192.168.x.y - # None Y 0.0.0.0 - # None N 127.0.0.1 - host = None - flags = socket.AI_PASSIVE - try: - info = socket.getaddrinfo(host, port, socket.AF_UNSPEC, - socket.SOCK_STREAM, 0, flags) - except socket.gaierror: - # Probably a DNS issue. Assume IPv4. - info = [(socket.AF_INET, socket.SOCK_STREAM, 0, "", self.bind_addr)] - - self.socket = None - msg = "No socket could be created" - for res in info: - af, socktype, proto, canonname, sa = res - try: - self.bind(af, socktype, proto) - except socket.error, msg: - if self.socket: - self.socket.close() - self.socket = None - continue - break - if not self.socket: - raise socket.error, msg - - # Timeout so KeyboardInterrupt can be caught on Win32 - self.socket.settimeout(1) - self.socket.listen(self.request_queue_size) - - # Create worker threads - for i in xrange(self.numthreads): - self._workerThreads.append(WorkerThread(self)) - for worker in self._workerThreads: - worker.setName("CP WSGIServer " + worker.getName()) - worker.start() - for worker in self._workerThreads: - while not worker.ready: - time.sleep(.1) - self.ready = True - - def start(self): - self.start_common() - while self.ready: - self.tick() - if self.interrupt: - while self.interrupt is True: - # Wait for self.stop() to complete. See _set_interrupt. - time.sleep(0.1) - raise self.interrupt - - def start_gtk(self): - self.start_common() - self.socket.settimeout(0.0001) - self.timeout = 0.3 - self.gtk_idle_id = gobject.idle_add(self.tick) - #self.gtk_idle_id = gobject.timeout_add(100, self.tick) #needs tweaking! - - - def bind(self, family, type, proto=0): - """Create (or recreate) the actual socket object.""" - self.socket = socket.socket(family, type, proto) - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) -## self.socket.setsockopt(socket.SOL_SOCKET, socket.TCP_NODELAY, 1) - if self.ssl_certificate and self.ssl_private_key: - if SSL is None: - raise ImportError("You must install pyOpenSSL to use HTTPS.") - - # See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442473 - ctx = SSL.Context(SSL.SSLv23_METHOD) - ctx.use_privatekey_file(self.ssl_private_key) - ctx.use_certificate_file(self.ssl_certificate) - self.socket = SSLConnection(ctx, self.socket) - self.populate_ssl_environ() - self.socket.bind(self.bind_addr) - - def tick(self): - """Accept a new connection and put it on the Queue.""" - #print 'tick!' - try: - s, addr = self.socket.accept() - if not self.ready: - return True - if hasattr(s, 'settimeout'): - s.settimeout(self.timeout) - conn = self.ConnectionClass(s, addr, self) - self.requests.put(conn) - except socket.timeout: - # The only reason for the timeout in start() is so we can - # notice keyboard interrupts on Win32, which don't interrupt - # accept() by default - # mvoncken and i'ts usefull for gtk too. - return True - except socket.error, x: - msg = x.args[1] - if msg in ("Bad file descriptor", "Socket operation on non-socket"): - # Our socket was closed. - return True - if msg == "Resource temporarily unavailable": - # Just try again. See http://www.cherrypy.org/ticket/479. - return True - raise #mvoncken:should it raise here? - return True - - def _get_interrupt(self): - return self._interrupt - def _set_interrupt(self, interrupt): - self._interrupt = True - self.stop() - self._interrupt = interrupt - interrupt = property(_get_interrupt, _set_interrupt, - doc="Set this to an Exception instance to " - "interrupt the server.") - - def stop(self): - """Gracefully shutdown a server that is serving forever.""" - self.ready = False - - sock = getattr(self, "socket", None) - if sock: - if not isinstance(self.bind_addr, basestring): - # Touch our own socket to make accept() return immediately. - try: - host, port = sock.getsockname()[:2] - except socket.error, x: - if x.args[1] != "Bad file descriptor": - raise - else: - # Note that we're explicitly NOT using AI_PASSIVE, - # here, because we want an actual IP to touch. - # localhost won't work if we've bound to a public IP, - # but it would if we bound to INADDR_ANY via host = ''. - for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC, - socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - s = None - try: - s = socket.socket(af, socktype, proto) - # See http://groups.google.com/group/cherrypy-users/ - # browse_frm/thread/bbfe5eb39c904fe0 - s.settimeout(1.0) - s.connect((host, port)) - s.close() - except socket.error: - if s: - s.close() - if hasattr(sock, "close"): - sock.close() - self.socket = None - - # Must shut down threads here so the code that calls - # this method can know when all threads are stopped. - for worker in self._workerThreads: - self.requests.put(_SHUTDOWNREQUEST) - - # Don't join currentThread (when stop is called inside a request). - current = threading.currentThread() - while self._workerThreads: - worker = self._workerThreads.pop() - if worker is not current and worker.isAlive: - try: - worker.join() - except AssertionError: - pass - - def stop_gtk(self): - self.stop() - if self.gtk_idle_id == None: - raise Exception('gtk_idle_id == None in stop_gtk') - gobject.source_remove(self.gtk_idle_id) - self.gtk_idle_id = None - - - def populate_ssl_environ(self): - """Create WSGI environ entries to be merged into each request.""" - cert = open(self.ssl_certificate).read() - cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert) - self.ssl_environ = { - # pyOpenSSL doesn't provide access to any of these AFAICT -## 'SSL_PROTOCOL': 'SSLv2', -## SSL_CIPHER string The cipher specification name -## SSL_VERSION_INTERFACE string The mod_ssl program version -## SSL_VERSION_LIBRARY string The OpenSSL program version - } - - # Server certificate attributes - self.ssl_environ.update({ - 'SSL_SERVER_M_VERSION': cert.get_version(), - 'SSL_SERVER_M_SERIAL': cert.get_serial_number(), -## 'SSL_SERVER_V_START': Validity of server's certificate (start time), -## 'SSL_SERVER_V_END': Validity of server's certificate (end time), - }) - - for prefix, dn in [("I", cert.get_issuer()), - ("S", cert.get_subject())]: - # X509Name objects don't seem to have a way to get the - # complete DN string. Use str() and slice it instead, - # because str(dn) == "" - dnstr = str(dn)[18:-2] - - wsgikey = 'SSL_SERVER_%s_DN' % prefix - self.ssl_environ[wsgikey] = dnstr - - # The DN should be of the form: /k1=v1/k2=v2, but we must allow - # for any value to contain slashes itself (in a URL). - while dnstr: - pos = dnstr.rfind("=") - dnstr, value = dnstr[:pos], dnstr[pos + 1:] - pos = dnstr.rfind("/") - dnstr, key = dnstr[:pos], dnstr[pos + 1:] - if key and value: - wsgikey = 'SSL_SERVER_%s_DN_%s' % (prefix, key) - self.ssl_environ[wsgikey] = value - - diff --git a/plugins/WebUi/lib/readme.txt b/plugins/WebUi/lib/readme.txt deleted file mode 100644 index 16c5eee85..000000000 --- a/plugins/WebUi/lib/readme.txt +++ /dev/null @@ -1,8 +0,0 @@ -This folder may only contain general purpose utilities/files/tools. -They should be usable outside of deluge. - -Disclaimer: - -Some may have been adapted to work better with deluge. -But they will import other parts of deluge or Webui. - diff --git a/plugins/WebUi/revno b/plugins/WebUi/revno deleted file mode 100644 index 730a054a0..000000000 --- a/plugins/WebUi/revno +++ /dev/null @@ -1 +0,0 @@ -172 diff --git a/plugins/WebUi/run_webserver b/plugins/WebUi/run_webserver deleted file mode 100755 index b8e9b47f5..000000000 --- a/plugins/WebUi/run_webserver +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env python -import deluge_webserver -deluge_webserver.run() diff --git a/plugins/WebUi/ssl/deluge.key b/plugins/WebUi/ssl/deluge.key deleted file mode 100644 index a9d5db5ce..000000000 --- a/plugins/WebUi/ssl/deluge.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEA1sPXr1O6l2J9NAEvEYQ/JFDSVcJHh9YxP7kPdjsu7k9Ih845 -BHMX52A3Ypbe5MHe2bCj/8dRYCixRdF1KUTAKXdzc7mw9prgf3sS3RvmfcRsln6u -x7XRg7YprZJ46hFmcHiUPRgtTFLuFO2YWBnqxu/caTtAxx3PdoK6LDVnuVjHYofC -8uD4A9k6yL/jj3Yrkf8WYQqJ6pJcMAz/2c8ZXlBuiUCb9j5xKTzYoJaiUkKN2YrA -hoxRxfI7Zc7MH2yWw8/fTZJbGXo8nrfek7coSE7yQS1M6ciwkYk5VO2mBVJBJgAT -QUR/jGfLzEqNKXghQ564v9wmuFmUMd99a0tkVwIDAQABAoIBACID6sluLYOEqefu -uBHCLG4IDwheOQ4esrYxDW3gedJs5EP+ObGmuQaAisUmuC7rNeysuYzteMoOJ+Wz -AyeCKB1pOfP+WTT12tDWIWq73InW7ov3jJ89AO4nj/pZ1KTeFKeDsZbrmWEZUXQn -HZX2pOTVYMeaBuyCoDVZBzuxSbhlON4wS6ClMhem+eBOxg351CDTZa2cbq7Ffcos -VP7LY2ORQYNDTQSLguV/dJrFSotB8Eoz2xIpg5XR7msp6lzPzyAd+Aoz/T1lYxCY -IFZCJYKnIpgoYQvmtUlhQrdD8P0J4Kth7I8NgkWvXCKazQjhpUm+wojLKD0G7Kcz -9znIV+ECgYEA+qfp1C8jWbaAn1yAeORUA9aB6aGIURfOpZjnCvtMWM0Nu0nAJYDv -X7L5GRa1ulfKhfUG1Jv/ynMKXYuBUDhyccYLpP7BHpd29Arr7YAgb52KaD1PoKNa -Z45c61dj4sFoCmJEbDoL21UGb0LX3mc4XzPzwWs8AKfLW4aZh1NwCisCgYEA21gJ -Hy3egBgMT9+nVjqsgtIXgJOnzQRhvRwT7IFf392ZyFi8iM+pDUsx1yj0zSG4XNPw -NY8VtZuTBUlG73RKcrrz31jhCMfLCnoRkQeweZv0QWzbLU3V8DleUYdjFc/t0me5 -4NBR9lBlwYHgyU3GQ814vum+m0IAH0Ng1UxAVIUCgYAFOHwZTEYLN07kgtO2MOND -FTOtfwzMy5clQdMGGofTjanMjdOvtEjIEH05tYxhbjSsp5bV1M32FIFRw3cVCafw -kLRrYlb5YSQ8HwIc9z81s+1PEH/ZE63tXDy5Nh/BeE/Hb5aHPopCrjmtFZJTcojt -CrL4A1jDlrsYk+wcsnMx8wKBgEhJJQhvd2pDgps4G8+hGoUqc7Bd+OjpzsQh4rcI -k+4U+7847zkvJolJBK3hw3tu53FAL2OXOhJVqQgO9B+p9XcGAaTTh6X7IgDb5bok -DJanPMHq+/hcNGssnNbFhXQEyF2U7X8XaEuCh2ZURR5SUUq7BlX0dmp4P84NyHXC -4Vh5AoGAZYWkXxQUGzVm+H3fPpmETWGRNFDTimzi+6N+/uHkqkiDa3LGSnabmKh+ -voKm//DUjEVGlAZ3CGOjO/5SlZc/zjkgh1vg7KOU4x7DqVOuZjom5Tx3ZI4xVVVt -tVtvK0qjzUTVcwAQALN/PNak+gs9534e954rmA9kmc3xBe4ho9M= ------END RSA PRIVATE KEY----- diff --git a/plugins/WebUi/ssl/deluge.pem b/plugins/WebUi/ssl/deluge.pem deleted file mode 100644 index effef476e..000000000 --- a/plugins/WebUi/ssl/deluge.pem +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDlzCCAn+gAwIBAgIJAPnW/GEzRy8xMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV -BAYTAkFVMRUwEwYDVQQIEwxUaGUgSW50ZXJuZXQxFTATBgNVBAoTDERlbHVnZSBX -ZWJ1aTAeFw0wNzExMjQxMDAzNDRaFw0wODExMjMxMDAzNDRaMDsxCzAJBgNVBAYT -AkFVMRUwEwYDVQQIEwxUaGUgSW50ZXJuZXQxFTATBgNVBAoTDERlbHVnZSBXZWJ1 -aTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANbD169TupdifTQBLxGE -PyRQ0lXCR4fWMT+5D3Y7Lu5PSIfOOQRzF+dgN2KW3uTB3tmwo//HUWAosUXRdSlE -wCl3c3O5sPaa4H97Et0b5n3EbJZ+rse10YO2Ka2SeOoRZnB4lD0YLUxS7hTtmFgZ -6sbv3Gk7QMcdz3aCuiw1Z7lYx2KHwvLg+APZOsi/4492K5H/FmEKieqSXDAM/9nP -GV5QbolAm/Y+cSk82KCWolJCjdmKwIaMUcXyO2XOzB9slsPP302SWxl6PJ633pO3 -KEhO8kEtTOnIsJGJOVTtpgVSQSYAE0FEf4xny8xKjSl4IUOeuL/cJrhZlDHffWtL -ZFcCAwEAAaOBnTCBmjAdBgNVHQ4EFgQU1BbX1/4WtAKRKmWI1gqryIoj7BQwawYD -VR0jBGQwYoAU1BbX1/4WtAKRKmWI1gqryIoj7BShP6Q9MDsxCzAJBgNVBAYTAkFV -MRUwEwYDVQQIEwxUaGUgSW50ZXJuZXQxFTATBgNVBAoTDERlbHVnZSBXZWJ1aYIJ -APnW/GEzRy8xMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAEoiSz5x -hRCplxUG34g3F5yJe0QboqzJ/XmECfO80a980C/WVeivM2Kb1uafsKNp+WK7wD8g -mei+todYXG+fD8WmG41LG87Xi2Xe4SlAcemEpGcC5F1bpCdvqnVAWFnqoF88FOHx -NDlrq5H5lhMH9wVrX9qJvxL+StaDJ0sFk4kMGWEN+bdSYfFdBQzF903nPtm+PlvO -1Uo6gCuRTMYM5J1DC/GpNpo/Fzrkgm8mMf1MYy3rljiNgMt2rnxhtwi6jugwyMui -id6Of6gYAtvhi7kmaUpdI5PHO35dqRK7pHXH+YXaulosCPw/+bSRptFTykeEMrBj -CzotqJ+74MwXZyM= ------END CERTIFICATE----- diff --git a/plugins/WebUi/static/images/downloading16.png b/plugins/WebUi/static/images/downloading16.png deleted file mode 100644 index 53a2b6e61..000000000 Binary files a/plugins/WebUi/static/images/downloading16.png and /dev/null differ diff --git a/plugins/WebUi/static/images/inactive16.png b/plugins/WebUi/static/images/inactive16.png deleted file mode 100644 index 10342be18..000000000 Binary files a/plugins/WebUi/static/images/inactive16.png and /dev/null differ diff --git a/plugins/WebUi/static/images/seeding16.png b/plugins/WebUi/static/images/seeding16.png deleted file mode 100644 index 6994323de..000000000 Binary files a/plugins/WebUi/static/images/seeding16.png and /dev/null differ diff --git a/plugins/WebUi/static/simple_site_style.css b/plugins/WebUi/static/simple_site_style.css deleted file mode 100755 index 3776994e8..000000000 --- a/plugins/WebUi/static/simple_site_style.css +++ /dev/null @@ -1,91 +0,0 @@ -/* ----------------------------------------------------------- Theme Name: Simple Theme URI: http://deluge-torrent.org Description: Deluge Theme Version: 1.0 ----------------------------------------------------------- */ BODY { background: #304663 url(images/simple_bg.jpg) repeat-x; font-family: trebuchet ms; font-size: 10pt; margin: 0; } /* GENERIC STYLES */ a img {border: 0px} hr {color: #627082; margin: 15px 0 15px 0;} /* STRUCTURE */ #page { min-width: 800px; margin-left: auto; margin-right: auto; } #main_content { background:url(images/simple_line.jpg) repeat-x; } #simple_logo { background:url(images/simple_logo.jpg) no-repeat; } #main { padding-top: 20px; padding-left: 20px; color: #fff; } #main form table { border: #2a425c 1px solid; } #main form table tr { border: 0px; } #main form table tr th { background: #1f3044; font-size: 16px; border: 0px; - white-space: nowrap; } #main form table tr td{ border: 0px; color: #fff; font-size: 12px; white-space: nowrap; } #main form table tr th a { color: #8fa6c3; font-size: 16px; white-space: nowrap; } #main form table tr th a, a:active, a:visited { color: #8fa6c3; text-decoration: none; } #main form table tr th a:hover {color: #fff; text-decoration: underline;} #main form table tr td a { color: #fff; font-size: 12px; white-space: nowrap; } #main form table tr td a, a:active, a:visited { color: #fff; text-decoration: none;} #main form table tr td a:hover {color: #fff; text-decoration: underline;} #main a { color: #fff; font-size: 12px; } #main a, a:active, a:visited { color: #fff; text-decoration: none;} #main a:hover {color: #fff; text-decoration: underline;} .info { text-align: right; padding: 0 50px 0 0; color: #8fa6c3; font-size: 16px; letter-spacing: 4px; font-weight: bold; } .title { color: #dce4ee; font-size: 32px; padding: 10px 50px 0 0; text-align: right; } .title a, a:active, a:visited { color: #dce4ee; text-decoration: none;} .title a:hover {color: #fff; text-decoration: underline;} #button { border:1px solid #23344b; background: #99acc3; color: #000; font-family:verdana, arial, helvetica, sans-serif; font-size:10px; margin-top:5px; } INPUT{ border:1px solid #23344b; background: #99acc3; color: #000; } TEXTAREA{ border:1px solid #23344b; background: #99acc3; width:480px; } .footertext a { color: #c0c0c0; text-decoration:none;} .footertext a:visited { color: #c0c0c0; text-decoration:none;} .footertext a:active { color: #c0c0c0; text-decoration:none;} .footertext a:hover {color: #fff; text-decoration: underline;} .footertext { text-align: center; padding: 60px 0 0 0; font-size: 8pt; left: -100px; font-family: trebuchet MS; color: #fff; position: relative; } .clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } div.progress_bar{ background-color:#4573a5; /*color:blue;*/ -moz-border-radius:5px; /*ff only setting*/ } - -div.progress_bar_outer { /*used in table-view*/ - width:150px; -} - td.progress_bar { white-space: nowrap; } td.info_label { font-weight: bold; } td { font-size: 10pt; color: #d1dae5; white-space: nowrap; } tr { - font-size: 10pt; - color: #d1dae5; -} - -div.panel { - padding:10px; - width:750px; - background-color: #37506f; - -moz-border-radius:10px; /*ff-only!*/ - margin-top:10px; - margin-bottom:10px; -} - - -/*New styles:*/ - -div.deluge_button { - display:inline; -} -form.deluge_button { - display:inline; -} -button.deluge_button { - background-color: #37506f; - border:1px solid #68a; - - background: #99acc3; - color: #000; - vertical-align:middle; - -moz-border-radius:7px; -} -button.deluge_button:hover { - background-color:#68a; -} -div.error { - background-color:#FFFFFF; - color:#AA0000; - font-weight:bold; - -moz-border-radius:10px; - width:200px; - margin-bottom:20px; - padding:10px; - -} - -/*tr.torrent_table:hover { - background-color:#68a; -}*/ - -tr.torrent_table_selected { - background-color:#900; -} - - -img.button { - margin-bottom:0px; - padding:0px; - position:relative; - top:2px; -} - -body.inner { - background:none; -} - - -form.pause_resume { - margin:0; - padding:0; - border:0; -} - -th { - background: #1f3044; - font-size: 14px; - border: 0px; - white-space: nowrap; -} - -#torrent_table { - border: #2a425c 1px solid; -} - - /* Hides from IE-mac \*/ * html .clearfix {height: 1%;} .clearfix {display: block;} /* End hide from IE-mac */ diff --git a/plugins/WebUi/templates/advanced/header.html b/plugins/WebUi/templates/advanced/header.html deleted file mode 100644 index 3d8f4cda3..000000000 --- a/plugins/WebUi/templates/advanced/header.html +++ /dev/null @@ -1,28 +0,0 @@ -$def with (title) - - - Deluge:$title - - - - - - - - - - - -
        - - - - -
        - -
        -
        diff --git a/plugins/WebUi/templates/advanced/index.html b/plugins/WebUi/templates/advanced/index.html deleted file mode 100644 index e68712aca..000000000 --- a/plugins/WebUi/templates/advanced/index.html +++ /dev/null @@ -1,147 +0,0 @@ -$def with (torrent_list, all_torrents) -$:render.header(_('Torrent list')) - -
        - - - - - - - - - - - - - - - - - - $:category_tabs(all_torrents) - -
        - - -
        - - - - $:(sort_head('calc_state_str', 'S')) - $:(sort_head('queue_pos', '#')) - $:(sort_head('name', _('Name'))) - $:(sort_head('total_size', _('Size'))) - $:(sort_head('progress', _('Progress'))) - $if (not get('category')): - $:(sort_head('category', _('Tracker'))) - $:(sort_head('num_seeds', _('Seeders'))) - $:(sort_head('num_peers', _('Peers'))) - $:(sort_head('download_rate', _('Download'))) - $:(sort_head('upload_rate', _('Upload'))) - $:(sort_head('eta', _('Eta'))) - $:(sort_head('distributed_copies', _('Avail'))) - $:(sort_head('ratio', _('Ratio'))) - - - -$altrow(True) -$#4-space indentation is mandatory for for-loops in templetor! -$for torrent in torrent_list: - - - - - - - $if (not get('category')): - - - - - - - - - -
        -
        - -
        -
        $torrent.queue_pos - $(crop(torrent.name, 40))$fsize(torrent.total_size) -
        -
        - $torrent.message $int(torrent.progress) % -
        -
        -
        $torrent.category$torrent.num_seeds ($torrent.total_seeds)$torrent.num_peers ($torrent.total_peers) - $if (torrent.download_rate): - $fspeed(torrent.download_rate) - $else: -   - - $if (torrent.upload_rate): - $fspeed(torrent.upload_rate) - $else: -   - $torrent.eta$("%.3f" % torrent.distributed_copies)$("%.3f" % torrent.ratio) -
        -
        - - -$:part_stats() - -
        - -
        - -
        - - - - - -
        - -
        - - -$:render.footer() - diff --git a/plugins/WebUi/templates/advanced/part_categories.html b/plugins/WebUi/templates/advanced/part_categories.html deleted file mode 100644 index 3e8bbf806..000000000 --- a/plugins/WebUi/templates/advanced/part_categories.html +++ /dev/null @@ -1,37 +0,0 @@ -$def with (filter_tabs, category_tabs) -
        - - - - - - - -
        - - - - diff --git a/plugins/WebUi/templates/advanced/static/advanced.css b/plugins/WebUi/templates/advanced/static/advanced.css deleted file mode 100644 index 2ac3307f8..000000000 --- a/plugins/WebUi/templates/advanced/static/advanced.css +++ /dev/null @@ -1,264 +0,0 @@ -/* ----------------------------------------------------------- Theme Name: Simple Theme URI: http://deluge-torrent.org Description: Deluge Theme Version: 1.0 ----------------------------------------------------------- */ BODY { background: #304663 url(../../static/images/simple_bg.jpg) repeat-x; font-family: Bitstream Vera,Verdana; font-size: 10pt; margin: 0; - padding:0; - border:0; } /* GENERIC STYLES */ a img {border: 0px} hr {color: #627082; margin: 15px 0 15px 0;} -td {font-family: Bitstream Vera,Verdana;} -tr {font-family: Bitstream Vera,Verdana;} -table {font-family: Bitstream Vera,Verdana;} div {font-family: Bitstream Vera,Verdana;} /* STRUCTURE */ #page { min-width: 800px; margin-left: auto; margin-right: auto; - margin: 0; - padding:0; - font-family: Bitstream Vera,Verdana; } #main_content { background:url(../../static/images/simple_line.jpg) repeat-x; - margin: 0; - padding:0; } #simple_logo { background:url(../../static/images/simple_logo.jpg) no-repeat; } #main { - margin: 0; - padding:0; padding-top: 6px; color: #fff; } #main form table { border: #2a425c 1px solid; } #main form table tr { border: 0px; } #main form table tr th { background: #1f3044; font-size: 16px; border: 0px; - white-space: nowrap; } #main form table tr td{ border: 0px; color: #fff; font-size: 12px; white-space: nowrap; - font-family: Bitstream Vera,Verdana; } #main form table tr th a { color: #8fa6c3; font-size: 16px; white-space: nowrap; } #main form table tr th a, a:active, a:visited { color: #8fa6c3; text-decoration: none; } #main form table tr th a:hover {color: #fff; text-decoration: underline;} #main form table tr td a { color: #fff; font-size: 12px; white-space: nowrap; - font-family: Bitstream Vera,Verdana; } #main form table tr td a, a:active, a:visited { color: #fff; text-decoration: none;} #main form table tr td a:hover {color: #fff; text-decoration: underline;} #main a { color: #fff; font-size: 12px; } #main a, a:active, a:visited { color: #fff; text-decoration: none;} #main a:hover {color: #fff; text-decoration: underline;} .info { text-align: right; padding: 0 50px 0 0; color: #8fa6c3; font-size: 16px; letter-spacing: 4px; font-weight: bold; } .title { color: #dce4ee; font-size: 32px; padding: 10px 50px 0 0; text-align: right; } .title a, a:active, a:visited { color: #dce4ee; text-decoration: none;} .title a:hover {color: #fff; text-decoration: underline;} input{ - background-color: #37506f; - border:1px solid #68a; - - background: #99acc3; - color: #000; - /*vertical-align:middle;*/ - -moz-border-radius:5px; - /*margin-top:5px;*/ - } - -input:hover { - background-color:#68a; -} TEXTAREA{ border:1px solid #23344b; background: #99acc3; width:480px; } .footertext a { color: #c0c0c0; text-decoration:none;} .footertext a:visited { color: #c0c0c0; text-decoration:none;} .footertext a:active { color: #c0c0c0; text-decoration:none;} .footertext a:hover {color: #fff; text-decoration: underline;} .footertext { text-align: center; padding: 60px 0 0 0; font-size: 8pt; left: -100px; font-family: Bitstream Vera,Verdana; color: #fff; position: relative; } .clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } div.progress_bar{ background-color:#4573a5; /*color:blue;*/ -moz-border-radius:5px; /*ff only setting*/ } - -div.progress_bar_outer { /*used in table-view*/ - width:150px; -} - td.progress_bar { white-space: nowrap; } td.info_label { font-weight: bold; } td { font-size: 10pt; color: #d1dae5; white-space: nowrap; } tr { font-size: 10pt; color: #d1dae5; } - -div.panel { - padding:10px; - width:750px; - background-color: #37506f; - -moz-border-radius:10px; /*ff-only!*/ - margin-top:10px; - margin-bottom:10px; -} - - -/*New styles:*/ - -div.deluge_button { - display:inline; -} -form.deluge_button { - display:inline; -} -button.deluge_button { - background-color: #37506f; - border:1px solid #68a; - - background: #99acc3; - color: #000; - vertical-align:middle; - -moz-border-radius:7px; -} -button.deluge_button:hover { - background-color:#68a; -} -div.error { - background-color:#FFFFFF; - color:#AA0000; - font-weight:bold; - -moz-border-radius:10px; - width:200px; - margin-bottom:20px; - padding:10px; - -} - -tr.torrent_table:hover { - background-color:#68a; -} - -tr.altrow0:hover { - background-color:#68a; -} -tr.altrow1:hover { - background-color:#68a; -} - -tr.altrow1{ - background-color: #37506f; -} - - - -tr.torrent_table_selected { - background-color:#900; -} - -th.torrent_table:hover { - background-color:#68a; -} -th.torrent_table { - background-color: #37506f; -} - -img.button { - margin-bottom:0px; - padding:0px; - position:relative; - top:2px; -} - -body.inner { - background:none; -} - -#stats_panel { - -moz-border-radius:0px; - width:100%; - position:fixed; - bottom:0px; - left:0px; - background-color:#304663; - margin: 0; - padding:0; - text-align:left; - height:25px; - background-color:#ddd; - color:#000; - border-style:solid; - border:0; - border-top:1px; - border-color:#000; -} - -#about { - position:fixed; - bottom:0px; - right:10px; -} - -#info_panel_div2 { - position:fixed; - bottom:10px; - right:0px; - width:100%; - background-color:#304663; -} - -#refresh_panel { - -moz-border-radius:0px; - width:500px; - position:fixed; - bottom:0px; - right:0px; - background-color:#304663; - margin: 0; - padding:0; - text-align:right; - height:25px; - background-color:#ddd; - color:#000; - z-index:999; -} - -#refresh_panel button { - background-color:#304663; - color:#FFFFFF; - border:0; - position:relative; - top:0px; - height:20px; - background-color:#ddd; - color:#00F; -} - -#refresh_panel button:hover { - text-decoration: underline; -} - -#category_panel { - margin-bottom:0; - padding-bottom:0; - -moz-border-radius-bottomleft:0px; - -moz-border-radius-bottomright:0px; - padding-right:32px; -} - -#toolbar { - text-align:left; - margin-top:0; - padding-top:0; - margin-bottom: 30px; - -moz-border-radius-topleft:0px; - -moz-border-radius-topright:0px; - padding-top:5px; - padding-bottom:5px; - margin-bottom: 15px; - padding-left:32px; - height:20px; -} - -#toolbar select{ - /*border:1px solid #68a;*/ - border:0; - background-color: #37506f; - color: #FFF; -} -#toolbar select:hover{ - background-color:#68a; -} - -a.toolbar_btn { - width:20px; - height:20px; - padding-left:3px; - padding-top:7px; - padding-right:3px; - text-decoration: none; - margin-bottom:3px; -} -a.toolbar_btn:hover { - background-color:#68a; - -moz-border-radius:5px; - text-decoration: none; -} - - -#toolbar_refresh { - margin:0; - border:0; - background-color:none; - padding-left:2px; - padding-top:2px; - padding-right:2px; - text-decoration: none; - background-color: #37506f; - position:relative; - top:5px; -} -#toolbar_refresh:hover { - background-color:#68a; - -moz-border-radius:5px; - text-decoration: none; -} -#category_form{ - display:inline; - position:relative; - top:-3px; - padding-left:20px; -} - - -form { /*all forms!*/ - margin:0; - padding:0; - border:0; -} - -#torrent_list { - -moz-border-radius:7px; -} - /* Hides from IE-mac \*/ * html .clearfix {height: 1%;} .clearfix {display: block;} /* End hide from IE-mac */ - - diff --git a/plugins/WebUi/templates/advanced/static/scrolling_table.css b/plugins/WebUi/templates/advanced/static/scrolling_table.css deleted file mode 100644 index b046bd9c4..000000000 --- a/plugins/WebUi/templates/advanced/static/scrolling_table.css +++ /dev/null @@ -1,106 +0,0 @@ -/*Taken from: -http://www.imaputz.com/cssStuff/bigFourVersion.html -*/ - -/* define height and width of scrollable area. Add 16px to width for scrollbar */ -div.tableContainer { - clear: both; - /*border: 1px solid #963;*/ - height: 285px; - overflow: auto; - width: 756px; -} - -/* Reset overflow value to hidden for all non-IE browsers. */ -html>body div.tableContainer { - overflow: hidden; - width: 756px -} - -/* define width of table. IE browsers only */ -div.tableContainer table { - float: left; - width: 740px; -} - -/* define width of table. Add 16px to width for scrollbar. */ -/* All other non-IE browsers. */ -html>body div.tableContainer table { - width: 756px -} - -/* set table header to a fixed position. WinIE 6.x only */ -/* In WinIE 6.x, any element with a position property set to relative and is a child of */ -/* an element that has an overflow property set, the relative value translates into fixed. */ -/* Ex: parent element DIV with a class of tableContainer has an overflow property set to auto */ -thead.fixedHeader tr { - position: relative -} - -/* set THEAD element to have block level attributes. All other non-IE browsers */ -/* this enables overflow to work on TBODY element. All other non-IE, non-Mozilla browsers */ -html>body thead.fixedHeader tr { - display: block -} - -/* define the table content to be scrollable */ -/* set TBODY element to have block level attributes. All other non-IE browsers */ -/* this enables overflow to work on TBODY element. All other non-IE, non-Mozilla browsers */ -/* induced side effect is that child TDs no longer accept width: auto */ -html>body tbody.scrollContent { - display: block; - height: 262px; - overflow: auto; - width: 100% -} - -/* make TD elements pretty. Provide alternating classes for striping the table */ -/* http://www.alistapart.com/articles/zebratables/ */ -tbody.scrollContent td, tbody.scrollContent tr.normalRow td { - /*background: #FFF;*/ - - border-bottom: none; - border-left: none; - /*border-right: 1px solid #CCC; - border-top: 1px solid #DDD;*/ - padding: 2px 3px 3px 4px -} - -tbody.scrollContent tr.alternateRow td { - /*background: #EEE;*/ - border-bottom: none; - border-left: none; - /*border-right: 1px solid #CCC; - border-top: 1px solid #DDD;*/ - padding: 2px 3px 3px 4px -} - -/* define width of TH elements: 1st, 2nd, and 3rd respectively. */ -/* Add 16px to last TH for scrollbar padding. All other non-IE browsers. */ -/* http://www.w3.org/TR/REC-CSS2/selector.html#adjacent-selectors */ -html>body thead.fixedHeader th { - width: 200px -} - -html>body thead.fixedHeader th + th { - width: 240px -} - -html>body thead.fixedHeader th + th + th { - width: 316px -} - -/* define width of TD elements: 1st, 2nd, and 3rd respectively. */ -/* All other non-IE browsers. */ -/* http://www.w3.org/TR/REC-CSS2/selector.html#adjacent-selectors */ -html>body tbody.scrollContent td { - width: 200px -} - -html>body tbody.scrollContent td + td { - width: 240px -} - -html>body tbody.scrollContent td + td + td { - width: 300px -} \ No newline at end of file diff --git a/plugins/WebUi/templates/advanced/torrent_info_inner.html b/plugins/WebUi/templates/advanced/torrent_info_inner.html deleted file mode 100644 index 907bfcf55..000000000 --- a/plugins/WebUi/templates/advanced/torrent_info_inner.html +++ /dev/null @@ -1,15 +0,0 @@ -$def with (torrent) - - - - - Deluge:$torrent.name - - - - - - -$:render.tab_meta(torrent) - -$:render.footer() diff --git a/plugins/WebUi/templates/deluge/config.html b/plugins/WebUi/templates/deluge/config.html deleted file mode 100644 index e2670d0ae..000000000 --- a/plugins/WebUi/templates/deluge/config.html +++ /dev/null @@ -1,10 +0,0 @@ -$def with (form) -$:render.header(_('Config')) - -
        Not Implemented!
        -
        -$:form.render() - -
        - -$:render.footer() diff --git a/plugins/WebUi/templates/deluge/header.html b/plugins/WebUi/templates/deluge/header.html deleted file mode 100644 index 42cc62eed..000000000 --- a/plugins/WebUi/templates/deluge/header.html +++ /dev/null @@ -1,23 +0,0 @@ -$def with (title) - - - Deluge:$title - - - - - - - -
        - - - - -
        - -
        -
        diff --git a/plugins/WebUi/templates/deluge/part_stats.html b/plugins/WebUi/templates/deluge/part_stats.html deleted file mode 100644 index 134dcf4e7..000000000 --- a/plugins/WebUi/templates/deluge/part_stats.html +++ /dev/null @@ -1,38 +0,0 @@ -$def with (stats) - - -
        - -$_('Auto refresh:') -$if getcookie('auto_refresh') == '1': - ($getcookie('auto_refresh_secs')) $_('seconds')   - $:render.part_button('GET', '/refresh/set', _('Set'), 'tango/preferences-system.png') - $:render.part_button('POST', '/refresh/off', _('Disable'), 'tango/process-stop.png') -$else: - $_('Off')   - $:render.part_button('POST', '/refresh/on', _('Enable'), 'tango/view-refresh.png') -$#end - -$:render.part_button('POST', '/logout', _('Logout'), 'tango/system-log-out.png') - -
        - -
        - - - $_('Connections') : $stats.num_connections ($stats.max_num_connections) - - $_('Down Speed') : $stats.download_rate ($stats.max_download) - - $_('Up Speed') : $stats.upload_rate ($stats.max_upload) - - - - - - ($_('About')) - - -
        - - diff --git a/plugins/WebUi/templates/deluge/sort_column_head.html b/plugins/WebUi/templates/deluge/sort_column_head.html deleted file mode 100644 index d354a6c4f..000000000 --- a/plugins/WebUi/templates/deluge/sort_column_head.html +++ /dev/null @@ -1,12 +0,0 @@ -$def with (column_id, column_name, order, active_up, active_down) - - -$column_name\ -$if active_up: - -$if active_down: - - - - - diff --git a/plugins/WebUi/templates/deluge/torrent_add.html b/plugins/WebUi/templates/deluge/torrent_add.html deleted file mode 100644 index 0ceb15aae..000000000 --- a/plugins/WebUi/templates/deluge/torrent_add.html +++ /dev/null @@ -1,23 +0,0 @@ -$:render.header(_("Add Torrent")) -
        -
        - -
        -
        - $_('Url') - -
        -
        - $_('Upload torrent') - -
        -
        - - -
        -
        -
        -
        -$:render.footer() diff --git a/plugins/WebUi/templates/deluge/torrent_info.html b/plugins/WebUi/templates/deluge/torrent_info.html deleted file mode 100644 index 660273e1a..000000000 --- a/plugins/WebUi/templates/deluge/torrent_info.html +++ /dev/null @@ -1,50 +0,0 @@ -$def with (torrent) - -$:(render.header(torrent.message + '/' + torrent.name)) -
        -

        $_('Details')

        - -$:render.tab_meta(torrent) - -$if (torrent.action == 'start'): - $:render.part_button('POST', '/torrent/start/' + str(torrent.id), _('Resume'), 'tango/start.png') -$else: - $:render.part_button('POST', '/torrent/stop/' + str(torrent.id), _('Pause'), 'tango/pause.png') - - -$:render.part_button('GET', '/torrent/delete/' + str(torrent.id), _('Remove'), 'tango/list-remove.png') -$:render.part_button('POST', '/torrent/reannounce/' + str(torrent.id), _('Reannounce'), 'tango/view-refresh.png') - -$:render.part_button('POST', '/torrent/queue/up/' + str(torrent.id), _('Queue Up'), 'tango/queue-up.png') -$:render.part_button('POST', '/torrent/queue/down/' + str(torrent.id), _('Queue Down'), 'tango/queue-down.png') - -
        - - -
        - - - - -$:part_stats() - -$:render.footer() diff --git a/plugins/WebUi/version b/plugins/WebUi/version deleted file mode 100644 index 730a054a0..000000000 --- a/plugins/WebUi/version +++ /dev/null @@ -1 +0,0 @@ -172 diff --git a/plugins/WebUi/webserver_common.py b/plugins/WebUi/webserver_common.py deleted file mode 100644 index a169159fc..000000000 --- a/plugins/WebUi/webserver_common.py +++ /dev/null @@ -1,225 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright (C) Martijn Voncken 2007 -# -# 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 2, 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. - -""" -initializes config,render and proxy. -All hacks go here, so this is a really ugly source-file.. -Support running in process0.5 ,run inside-gtk0.5 and run in process0.6 -""" - -import os -import deluge -import random -import pickle -import sys -import base64 -from lib.webpy022 import template - -random.seed() -webui_path = os.path.dirname(__file__) -ENV = 'UNKNOWN' -config_defaults = { - "port":8112, - "button_style":2, - "auto_refresh":False, - "auto_refresh_secs": 10, - "template":"advanced", - "pwd_salt":"2540626806573060601127357001536142078273646936492343724296134859793541603059837926595027859394922651189016967573954758097008242073480355104215558310954", - "pwd_md5":"\xea\x8d\x90\x98^\x9f\xa9\xe2\x19l\x7f\x1a\xca\x82u%", - "cache_templates":False, - "use_https":False -} - -try: - _('translate something') -except: - import gettext - gettext.install('~/') - #log.error('no translations :(') - -try: - config_dir = deluge.common.CONFIG_DIR -except: - config_dir = os.path.expanduser("~/.config/deluge") - -config_file = os.path.join(config_dir,'webui.conf') -session_file = os.path.join(config_dir,'webui.sessions') - - -class subclassed_render(object): - """ - try to use the html template in configured dir. - not available : use template in /deluge/ - """ - def __init__(self, template_dirname, cache=False): - self.base_template = template.render( - os.path.join(webui_path, 'templates/deluge/'), - cache=cache) - - self.sub_template = template.render( - os.path.join(webui_path, 'templates/%s/' % template_dirname), - cache=cache) - - def __getattr__(self, attr): - if hasattr(self.sub_template, attr): - return getattr(self.sub_template, attr) - else: - return getattr(self.base_template, attr) - -def init_process(): - globals()['config'] = pickle.load(open(config_file)) - globals()['render'] = subclassed_render(config.get('template'), - config.get('cache_templates')) - -def init_06(): - import deluge.ui.client as proxy - from deluge.log import LOG as log - globals()['log'] = log - - proxy.set_core_uri('http://localhost:58846') #How to configure this? - - def add_torrent_filecontent(name , data_b64): - log.debug('monkeypatched add_torrent_filecontent:%s,len(data:%s))' % - (name , len(data_b64))) - - name = name.replace('\\','/') - name = 'deluge06_' + str(random.random()) + '_' + name.split('/')[-1] - filename = os.path.join('/tmp', name) - - log.debug('write: %s' % filename) - f = open(filename,"wb") - f.write(base64.b64decode(data_b64)) - f.close() - - proxy.add_torrent_file([filename]) - - - - - proxy.add_torrent_filecontent = add_torrent_filecontent - log.debug('cfg-file %s' % config_file) - if not os.path.exists(config_file): - log.debug('create cfg file %s' % config_file) - #load&save defaults. - f = file(config_file,'wb') - pickle.dump(config_defaults,f) - f.close() - - init_process() - globals()['proxy'] = proxy - globals()['ENV'] = '0.6' - - - -def init_05(): - import dbus - init_process() - bus = dbus.SessionBus() - proxy = bus.get_object("org.deluge_torrent.dbusplugin" - , "/org/deluge_torrent/DelugeDbusPlugin") - - globals()['proxy'] = proxy - globals()['ENV'] = '0.5_process' - init_logger() - -def init_gtk_05(): - #appy possibly changed config-vars, only called in when runing inside gtk. - from dbus_interface import get_dbus_manager - globals()['proxy'] = get_dbus_manager() - globals()['config'] = deluge.pref.Preferences(config_file, False) - globals()['render'] = subclassed_render(config.get('template'), - config.get('cache_templates')) - globals()['ENV'] = '0.5_gtk' - init_logger() - -def init_logger(): - #only for 0.5.. - import logging - logging.basicConfig(level=logging.DEBUG, - format="[%(levelname)s] %(message)s") - globals()['log'] = logging - - -#hacks to determine environment, TODO: clean up. -if 'env=0.5' in sys.argv: - init_05() -elif 'env=0.6' in sys.argv: - init_06() -elif hasattr(deluge, 'ui'): - init_06() -elif not hasattr(deluge,'pref'): - init_05() - - -#constants -REVNO = open(os.path.join(os.path.dirname(__file__),'revno')).read() -VERSION = open(os.path.join(os.path.dirname(__file__),'version')).read() - -TORRENT_KEYS = ['distributed_copies', 'download_payload_rate', - 'eta', 'is_seed', 'name', 'next_announce', - 'num_files', 'num_peers', 'num_pieces', 'num_seeds', 'paused', - 'piece_length','progress', 'ratio', 'total_done', 'total_download', - 'total_payload_download', 'total_payload_upload', 'total_peers', - 'total_seeds', 'total_size', 'total_upload', 'total_wanted', - 'tracker_status', 'upload_payload_rate', - 'uploaded_memory','tracker','state','queue_pos','user_paused'] - -STATE_MESSAGES = (_("Queued"), - _("Checking"), - _("Connecting"), - _("Downloading Metadata"), - _("Downloading"), - _("Finished"), - _("Seeding"), - _("Allocating")) - -SPEED_VALUES = [ - (-1, 'Unlimited'), - (5, '5.0 Kib/sec'), - (10, '10.0 Kib/sec'), - (15, '15.0 Kib/sec'), - (25, '25.0 Kib/sec'), - (30, '30.0 Kib/sec'), - (50, '50.0 Kib/sec'), - (80, '80.0 Kib/sec'), - (300, '300.0 Kib/sec'), - (500, '500.0 Kib/sec') - ] - -#try: -# SESSIONS = pickle.load(open(session_file)) -#except: -SESSIONS = [] - - - - - diff --git a/plugins/WebUi/webserver_framework.py b/plugins/WebUi/webserver_framework.py deleted file mode 100644 index b72acab66..000000000 --- a/plugins/WebUi/webserver_framework.py +++ /dev/null @@ -1,424 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# webserver_framework.py -# -# Copyright (C) Martijn Voncken 2007 -# -# 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 2, 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. - -""" -Todo's before stable: --__init__:kill->restart is not waiting for kill to be finished. ---later/features:--- --alternating rows? --set prio --clear finished? --torrent files. -""" -import lib.webpy022 as web - -from lib.webpy022.webapi import cookies, setcookie as w_setcookie -from lib.webpy022.http import seeother, url -from lib.webpy022 import template,changequery as self_url -from lib.webpy022.utils import Storage -from lib.static_handler import static_handler - -from deluge.common import fsize,fspeed - -import traceback -import random -from operator import attrgetter -import datetime -import pickle -from md5 import md5 -from urlparse import urlparse - -from deluge import common -from webserver_common import REVNO, VERSION, log -import webserver_common as ws -from debugerror import deluge_debugerror - -#init: -web.webapi.internalerror = deluge_debugerror -#/init -debug_unicode = False -#methods: -def setcookie(key, val): - """add 30 days expires header for persistent cookies""" - return w_setcookie(key, val , expires=2592000) - -#really simple sessions, to bad i had to implement them myself. -def start_session(): - log.debug('start session') - session_id = str(random.random()) - ws.SESSIONS.append(session_id) - #if len(ws.SESSIONS) > 20: #save max 20 sessions? - # ws.SESSIONS = ws.SESSIONS[-20:] - #not thread safe! , but a verry rare bug. - #f = open(ws.session_file,'wb') - #pickle.dump(ws.SESSIONS, f) - #f.close() - setcookie("session_id", session_id) - -def end_session(): - session_id = getcookie("session_id") - #if session_id in ws.SESSIONS: - # ws.SESSIONS.remove(session_id) - #not thread safe! , but a verry rare bug. - #f = open(ws.session_file,'wb') - #pickle.dump(ws.SESSIONS, f) - #f.close() - setcookie("session_id","") - -def do_redirect(): - """for redirects after a POST""" - vars = web.input(redir = None) - ck = cookies() - url_vars = {} - - if vars.redir: - seeother(vars.redir) - return - #todo:cleanup - if ("order" in ck and "sort" in ck): - url_vars.update({'sort':ck['sort'] ,'order':ck['order'] }) - if ("filter" in ck) and ck['filter']: - url_vars['filter'] = ck['filter'] - if ("category" in ck) and ck['category']: - url_vars['category'] = ck['category'] - - seeother(url("/index", **url_vars)) - -def error_page(error): - web.header("Content-Type", "text/html; charset=utf-8") - web.header("Cache-Control", "no-cache, must-revalidate") - print ws.render.error(error) - -def getcookie(key, default = None): - key = str(key).strip() - ck = cookies() - return ck.get(key, default) - -#deco's: -def deluge_page_noauth(func): - """ - add http headers - print result of func - """ - def deco(self, name = None): - web.header("Content-Type", "text/html; charset=utf-8") - web.header("Cache-Control", "no-cache, must-revalidate") - res = func(self, name) - print res - deco.__name__ = func.__name__ - return deco - -def check_session(func): - """ - a decorator - return func if session is valid, else redirect to login page. - """ - def deco(self, name = None): - log.debug('%s.%s(name=%s)' % (self.__class__.__name__, func.__name__, - name)) - vars = web.input(redir_after_login = None) - ck = cookies() - if ck.has_key("session_id") and ck["session_id"] in ws.SESSIONS: - return func(self, name) #ok, continue.. - elif vars.redir_after_login: - seeother(url("/login",redir=self_url())) - else: - seeother("/login") #do not continue, and redirect to login page - return deco - -def deluge_page(func): - return check_session(deluge_page_noauth(func)) - -#combi-deco's: -def auto_refreshed(func): - "decorator:adds a refresh header" - def deco(self, name = None): - if getcookie('auto_refresh') == '1': - web.header("Refresh", "%i ; url=%s" % - (int(getcookie('auto_refresh_secs',10)),self_url())) - return func(self, name) - deco.__name__ = func.__name__ - return deco - -def remote(func): - "decorator for remote api's" - def deco(self, name = None): - try: - log.debug('%s.%s(%s)' ,self.__class__.__name__, func.__name__,name ) - print func(self, name) - except Exception, e: - print 'error:%s' % e.message - print '-'*20 - print traceback.format_exc() - deco.__name__ = func.__name__ - return deco - -#utils: -def check_pwd(pwd): - m = md5() - m.update(ws.config.get('pwd_salt')) - m.update(pwd) - return (m.digest() == ws.config.get('pwd_md5')) - -def get_stats(): - stats = Storage({ - 'download_rate':fspeed(ws.proxy.get_download_rate()), - 'upload_rate':fspeed(ws.proxy.get_upload_rate()), - 'max_download':ws.proxy.get_config_value('max_download_speed_bps'), - 'max_upload':ws.proxy.get_config_value('max_upload_speed_bps'), - 'num_connections':ws.proxy.get_num_connections(), - 'max_num_connections':ws.proxy.get_config_value('max_connections_global') - }) - if stats.max_upload < 0: - stats.max_upload = _("Unlimited") - else: - stats.max_upload = fspeed(stats.max_upload) - - if stats.max_download < 0: - stats.max_download = _("Unlimited") - else: - stats.max_download = fspeed(stats.max_download) - - return stats - - -def get_torrent_status(torrent_id): - """ - helper method. - enhance ws.proxy.get_torrent_status with some extra data - """ - status = Storage(ws.proxy.get_torrent_status(torrent_id,ws.TORRENT_KEYS)) - - #add missing values for deluge 0.6: - for key in ws.TORRENT_KEYS: - if not key in status: - status[key] = 0 - - status["id"] = torrent_id - - url = urlparse(status.tracker) - if hasattr(url,'hostname'): - status.category = url.hostname or 'unknown' - else: - status.category = 'No-tracker' - - #0.5-->0.6 - status.download_rate = status.download_payload_rate - status.upload_rate = status.upload_payload_rate - - #for naming the status-images - status.calc_state_str = "downloading" - if status.paused: - status.calc_state_str= "inactive" - elif status.is_seed: - status.calc_state_str = "seeding" - - #action for torrent_pause - if status.user_paused: - status.action = "start" - else: - status.action = "stop" - - if status.user_paused: - status.message = _("Paused") - elif status.paused: - status.message = _("Queued") - else: - status.message = (ws.STATE_MESSAGES[status.state]) - - #add some pre-calculated values - status.update({ - "calc_total_downloaded" : (fsize(status.total_done) - + " (" + fsize(status.total_download) + ")"), - "calc_total_uploaded": (fsize(status.uploaded_memory - + status.total_payload_upload) + " (" - + fsize(status.total_upload) + ")"), - }) - - #no non-unicode string may enter the templates. - #FIXED,l was a translation bug.. - if debug_unicode: - for k, v in status.iteritems(): - if (not isinstance(v, unicode)) and isinstance(v, str): - try: - status[k] = unicode(v) - except: - raise Exception('Non Unicode for key:%s' % (k, )) - return status - -def get_categories(torrent_list): - trackers = [(torrent['category'] or 'unknown') for torrent in torrent_list] - categories = {} - for tracker in trackers: - categories[tracker] = categories.get(tracker,0) + 1 - return categories - -def filter_torrent_state(torrent_list,filter_name): - filters = { - 'downloading': lambda t: (not t.paused and not t.is_seed) - ,'queued':lambda t: (t.paused and not t.user_paused) - ,'paused':lambda t: (t.user_paused) - ,'seeding':lambda t:(t.is_seed and not t.paused ) - ,'traffic':lambda t: (t.download_rate > 0 or t.upload_rate > 0) - } - filter_func = filters[filter_name] - return [t for t in torrent_list if filter_func(t)] - -#/utils - -#template-defs: - -def get_category_choosers(torrent_list): - """ - todo: split into 2 parts... - """ - categories = get_categories(torrent_list) - - filter_tabs = [Storage(title='All (%s)' % len(torrent_list), - filter='', category=None)] - - #static filters - for title, filter_name in [ - (_('Downloading'),'downloading') , - (_('Queued'),'queued') , - (_('Paused'),'paused') , - (_('Seeding'),'seeding'), - (_('Traffic'),'traffic') - ]: - title += ' (%s)' % ( - len(filter_torrent_state(torrent_list, filter_name)), ) - filter_tabs.append(Storage(title=title, filter=filter_name)) - - categories = [x for x in get_categories(torrent_list).iteritems()] - categories.sort() - - #trackers: - category_tabs = [] - category_tabs.append( - Storage(title=_('Trackers'),category='')) - for title,count in categories: - category = title - title += ' (%s)' % (count, ) - category_tabs.append(Storage(title=title, category=category)) - - return filter_tabs, category_tabs - -def category_tabs(torrent_list): - filter_tabs, category_tabs = get_category_choosers(torrent_list) - return ws.render.part_categories(filter_tabs, category_tabs) - - -def template_crop(text, end): - if len(text) > end: - return text[0:end - 3] + '...' - return text - -def template_sort_head(id,name): - #got tired of doing these complex things inside templetor.. - vars = web.input(sort = None, order = None) - active_up = False - active_down = False - order = 'down' - - if vars.sort == id: - if vars.order == 'down': - order = 'up' - active_down = True - else: - active_up = True - - return ws.render.sort_column_head(id, name, order, active_up, active_down) - -def template_part_stats(): - return ws.render.part_stats(get_stats()) - -def get_config(var): - return ws.config.get(var) - -irow = 0 -def altrow(reset = False): - global irow - if reset: - irow = 1 - return - irow +=1 - irow = irow % 2 - return "altrow%s" % irow - - -template.Template.globals.update({ - 'sort_head': template_sort_head, - 'part_stats':template_part_stats, - 'category_tabs':category_tabs, - 'crop': template_crop, - '_': _ , #gettext/translations - 'str': str, #because % in templetor is broken. - 'int':int, - 'sorted': sorted, - 'altrow':altrow, - 'get_config': get_config, - 'self_url': self_url, - 'fspeed': common.fspeed, - 'fsize': common.fsize, - 'render': ws.render, #for easy resuse of templates - 'rev': 'rev.%s' % (REVNO, ), - 'version': VERSION, - 'getcookie':getcookie, - 'get': lambda (var): getattr(web.input(**{var:None}), var) # unreadable :-( -}) -#/template-defs - -def create_webserver(urls, methods): - from lib.webpy022.request import webpyfunc - from lib.webpy022 import webapi - from lib.gtk_cherrypy_wsgiserver import CherryPyWSGIServer - import os - - func = webapi.wsgifunc(webpyfunc(urls, methods, False)) - server_address=("0.0.0.0", int(ws.config.get('port'))) - - server = CherryPyWSGIServer(server_address, func, server_name="localhost") - if ws.config.get('use_https'): - server.ssl_certificate = os.path.join(ws.webui_path,'ssl/deluge.pem') - server.ssl_private_key = os.path.join(ws.webui_path,'ssl/deluge.key') - - print "http://%s:%d/" % server_address - return server - -#------ -__all__ = ['deluge_page_noauth', 'deluge_page', 'remote', - 'auto_refreshed', 'check_session', - 'do_redirect', 'error_page','start_session','getcookie' - ,'setcookie','create_webserver','end_session', - 'get_torrent_status', 'check_pwd','static_handler','get_categories' - ,'template','filter_torrent_state','log'] diff --git a/po/POTFILES.in b/po/POTFILES.in deleted file mode 100644 index 1e54707f3..000000000 --- a/po/POTFILES.in +++ /dev/null @@ -1,52 +0,0 @@ -glade/delugegtk.glade -glade/dgtkpopups.glade -glade/file_tab_menu.glade -glade/merge_dialog.glade -glade/preferences_dialog.glade -glade/torrent_menu.glade -glade/tray_menu.glade -glade/edit_trackers.glade -glade/aboutdialog.glade -glade/files_dialog.glade -glade/wizard.glade -src/tab_details.py -src/interface.py -src/plugins.py -src/core.py -src/files.py -src/dialogs.py -src/common.py -plugins/BlocklistImport/__init__.py -plugins/BlocklistImport/ui.py -plugins/BlocklistImport/text.py -plugins/BlocklistImport/peerguardian.py -plugins/DesiredRatio/__init__.py -plugins/TorrentPeers/__init__.py -plugins/TorrentPeers/tab_peers.py -plugins/TorrentCreator/torrentcreator.glade -plugins/TorrentCreator/__init__.py -plugins/TorrentNotification/notification_preferences.glade -plugins/TorrentNotification/__init__.py -plugins/NetworkHealth/__init__.py -plugins/NetworkHealth/plugin.py -plugins/EventLogging/event_logging_preferences.glade -plugins/EventLogging/__init__.py -plugins/EventLogging/tab_log.py -plugins/SpeedLimiter/__init__.py -plugins/NetworkGraph/tab_graph.py -plugins/NetworkGraph/__init__.py -plugins/TorrentFiles/tab_files.py -plugins/TorrentFiles/__init__.py -plugins/MoveTorrent/__init__.py -plugins/MoveTorrent/movetorrent.glade -plugins/WebSeed/__init__.py -plugins/WebSeed/webseed.glade -plugins/Scheduler/__init__.py -plugins/Scheduler/plugin.py -plugins/WebUi/__init__.py -plugins/WebUi/webserver_common.py -plugins/WebUi/deluge_webserver.py -plugins/WebUi/scripts/template_strings.py -plugins/FlexRSS/FlexRSS.glade -plugins/Search/searchdlg.glade -plugins/Search/__init__.py diff --git a/po/ar.po b/po/ar.po deleted file mode 100644 index e7550b28b..000000000 --- a/po/ar.po +++ /dev/null @@ -1,2465 +0,0 @@ -# Arabic translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-27 18:57+0000\n" -"Last-Translator: bob00work \n" -"Language-Team: Arabic \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "اضف تورنت" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "أضف" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "احذف التورنت" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "احذف" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "أخل التورنتات المبذورة" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "أخلِ" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "ابدأ أو استكمل التورنت" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "عاود" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "جمّد التورنت" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "جمد" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "قدم التورنت في الطابور" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "لأعلى" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "أخّر التورنت في الطابور" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "لأسفل" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "غيّر تفضيلات ديلَج" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "التفضيلات" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "ملحقات" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_ملف" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -#, fuzzy -msgid "_Add Torrent" -msgstr "_أضف تورنت" - -#: glade/delugegtk.glade:208 -#, fuzzy -msgid "Add _URL" -msgstr "أضف _راباط" - -#: glade/delugegtk.glade:216 -#, fuzzy -msgid "_Clear Completed" -msgstr "أ_خل التامة" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_حرّر" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "ملح_قات" - -#: glade/delugegtk.glade:302 -#, fuzzy -msgid "_Torrent" -msgstr "_تورنت" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "إ_عرض" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_شريط الأدوات" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_تفاصيل" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_أعمدة" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "الحجم" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "الحالة" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -#, fuzzy -msgid "Seeders" -msgstr "الباذرون" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "الأنداد" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "سرعة التنزيل" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "سرعة الرفع" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "الوقت المتبقي" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "التوافر" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "نسبة المشاركة" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_مساعدة" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "تبرع لتطوير دلوج" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "ت_برع" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_الصفحة الرئيسية" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_الأسئلة المتكررة" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "ال_مجتمع" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "ساعد في ترجمة هذه البرمجية" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_ترجم هذه البرمجية…" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "يشغّل مرشد إعدادات أول مرة" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_شغّل مرشد الإعدادات" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "تم تنزيله:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "تم رفعه:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "الباذرون:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "نسبة المشاركة:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "السرعة:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "الأنداد:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "الوقت المتبقي" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "القطع:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "التوافر:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "احصائيات" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "عدد الملفات:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "الحجم الكلي:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "المقتفي:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "حالة المقتفي:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "الإعلان القادم:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "الاسم:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "المسار:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "معلومات عن التورنت" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "تفاصيل" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"هل أنت متأكد من أنك تريد إزالة التورنتات المختراة من " -"دِلَج ؟ " - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "احذف الملفات التي نزلت" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "احذف ملف ‪.torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "أظهر/اخفِ" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "أضف تورنت…" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "أخل التامة" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "ا_فتح ملفا" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "اختر الكل" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "أزل اختيار الكل" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "لا تنزّله" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "عادية" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "مرتفعة" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "قصوى" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "دمج قوائم المقتفي" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "التورنت موجود مسبقا في دِلَج؛ أتريد دمج قوائم المقتفين؟" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "تفضيلات" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "اسأل أين تحُفظ كل تنزيلة" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "اختر مجلدا" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "احفظ كل ملفات تورنت في:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "احفظ كل التنزيلات في:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "موضع التزيل" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "حمّل تلقائيا كل ملفات تورنت الموجودة في:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "تحميل تلقائي" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "عدد التورنتات النشطة التي على دِلَج تشغيلها. -1 تعني بلا حد أقصى" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "أقصى عدد للتورنتات النشطة المتزامنة:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "فعّل انتقاء الملفات فبل تنزيل التورنت" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "أظهره فقط إن كان التورنت يحوي أكثر من ملف واحد" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "أعط أولوية أكبر لأول و آخر قطعتين من كل ملف في التورنت" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "ابدأ التورنت مجمدا" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "التورنتات" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"التخصيص الكامل يخصص كل المساحة المطلوبة لتخزين ملفات التورنت على و يحول دون " -"تشذّر القرص" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "استخدم التخصيص الكامل" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "التخصيص المدمج يخصص المساحة حين الحاجة إليها" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "استخدم التخصيص المدمج" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "التخصيص" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "تنزيلات" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "ملاحظة: التغييرات لن تطبق حتى يعاد تشغيل دِلَج." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "من:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "إلى:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "سيختار دِلَج تلقائيا منفذا مختلفا لاستخدامه في كل مرة." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "منافذ عشوائية" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "اختبر المنفذ النشط" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "المنفذ النشط:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "قد يزيد جدول التلبيد الموزع من عدد الاتصالات الفاعلة." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "فعّل جدول التلبد الموزع الاعتيادي" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "جدول التلبيد الموزع" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "تبادل الأنداد" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "دليل الأنداد المحلي" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "إضافات شبكية" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "واردة:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"معطّل\n" -"مفعّل\n" -"إجباري" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "صادرة:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "فضّل تعمية التيار كله" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "المستوى:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"المصافحة\n" -"التيار كله\n" -"أيا منهما" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "التعمية" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "الشبكة" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "ضع التورنتات في آخر الطابور عندما تبدأ في الَبذر" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "ضع التورنتات الجديدة في الطابور قبل التامة" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "أوقف بذر التورنتات عندما تصل نسبة مشاركاتها:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "أخل تلقائيا التورنتات التي تصل الحد الأقصى للمشاركة" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "عدد الساعات" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "يجري البذر" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "البذر" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"العدد الأقصى لعدد محاولات الاتصال في الثانية. الأعداد الكبيرة قد تعجز بعض " -"المسيّرات الرخيصة. -1 تعني لا حد أقصى." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "العدد الأقصى لعدد محاولات الاتصال في الثانية." - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "العدد الأقصى للرفعات لجميع التورنتات. -1 يعني لا حد أقصى." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "سرعة الرفع القصوى لجميع التورنتات. -1 تعني لا حد أقصى." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "سرعة التحميل القصوى لجميع التورنتات. -1 تعني لا حد أقصى." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "السرعة القصوى للتنزيل (ك.بايت/ ث)" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "العدد الأقصى للاتصالات المسموح بها. -1 تعني لا حد أقصى." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "أقصى عدد للاتصالات:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "السرعة القصوى للرفع (ك.بايت/ث)" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "عدد الرفعات" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"العدد الأقصى للاتصالات نصف المفتوحة. العدد الأكبر قد يعجز المسيرات الرخيصة. " -"1 تعني لا حد أقصى." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "العدد الأقصى للاتصالات نصف المفتوحة" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "الاستغلال العمومي لعرض النطاق" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "العدد الأقصى للرفعات للتورنت الواحد. -1 تعني لا حد أقصى." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "العدد الأقصى لعدد الاتصالات للتورنت الواحد. -1 تعني لا حد أقصى." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "استغلال عرض النطاق لكل تورنت" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "عرض النطاق" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "يؤثر على أنداد تورنت العاديين" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "وسيط الأنداد" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "المنفذ" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "الخادوم" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "كلمة السر" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "اسم المستخدم" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "نوع الوسيط" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "وسيط الأنداد" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "وسيط المتعقبين" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "وسيط المتعقبين" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "وسيط جدول التلبيدات الموزع" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "وسيط جدول التلبيدات الموزع" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "وسيط بذرات الوب" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "وسيط بذرات الوب" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "الوسطاء" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "فعل أيقونة صينية النظام" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "صغر إلى الصينية عند الغلق" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "ابدأ في الصينية" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "احمِ صينية النظام بكلمة سرّ" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "كلمة السر:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "صينية النظام" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "استخدم مؤشر التقدم المتقدم (يزيد قليلا من شَغل المعالج و الذاكرة)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "مؤشر التقدم التفصيلي" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "سيتحقق دِلَج من خواديمنا و ينبهك إن كانت كانت توجد إصدارة أحدث" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "نبهني عند وجود إصدراة أحدث" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "التحديثات" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"ساعدنا في تحسين دِلَج بإعلامنا عن أرقام إصدارات بيثون و PyGTK لديك،\n" -"و عن نظام التشغيل و نوع المعالج. لن ترسل أية بيانات أخرى عنك." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "معلومات النظام" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "أخرى" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "ا_فرض إعادة الفحص" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "_عاود" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_جمّد" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_أزل التورنت" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "خيارات الم_قتفي" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_حدّث المتعقب" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_عدّل المتعقبين" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "اكشط المتعقب" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_الطابور" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "اﻷع_لى" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "لأ_على" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "لأ_سفل" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "الأس_فل" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "اف_تح الدليل المحتوي" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "أ_ظهر دِلَج" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "عا_ود الكل" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "ج_مّد الكل" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "حد سرعة التن_زيل" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "حد سرعة ال_رفع" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "ا_خرج" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "حرّر المقتفين" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "تحرير المقتفين" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "اختيار ملف دِلَج" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "سيوزع الملف الآن على شبكة جدول التلبيد الموزع عديمة المقتفين" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "أشر علامة الخصوصية" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "إعدادات التشغيل الأول" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"سيسعادك هذا المرشد على شبط دِلَج كما تحب. إن كنت جديدا على دِلَج فرجاء لاحظ " -"أن معظم وظائف و ميزات دِلَج هي في صورة ملحقات يمكن تقعيلها بنقر \"الملحقات\" " -"في قائمة \"حرر\" أو شريط الأدوات." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"يتطلب دِلَج نطاقا من المنافذ ليستمع عليها إلى الاتصالات الواردة. المنافذ " -"القياسية التي يستخدمها بت تورنت هي 6881-6889، إلا أن معظم مقدمي خدمة الاتصال " -"بإنترنت يغلقون هذه المنافذ لذا فنحن نحثك على اختيار غيرها ما بين 49152 و " -"65535؛ أو يمكنك جعل دلَج يختارها عشوائيا." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "استخدم منافذ عشوائية_" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"أتريد أن يحفظ دِلَج التنزيلات في موضع محدد مسبقا أم تريد تحديد موضع الحفظ في " -"كل مرة؟" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "أسألني كل مرة أين يُحفظ الملف" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "احفظ كل التنزيلات في: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"رجاء حدد سرعة الرفع لوصلتك و التي سنقترح بناء عليها التضبيطات اللاحقة" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "العدد الأقصى للتورنتات النشطة" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8 ك بتة\n" -"56 ك بتة\n" -"64 ك بتة\n" -"96 ك بتة\n" -"128 ك بتة\n" -"192 ك بتة\n" -"256 ك بتة\n" -"384 ك بتة\n" -"512 ك بتة\n" -"640 ك بتة\n" -"768 ك بتة\n" -"1 م بتة\n" -"2 م بتة\n" -"10 م بتة\n" -"20 م بتة\n" -"40 م بتة\n" -"50 م بتة\n" -"100 م بتة" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "سرعة الرفع للخط:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_ساعدنا في تحسين دِلَج بإعلامنا عن أرقام إصدارات بيثون و PyGTK لديك،\n" -"و عن نظام التشغيل و نوع المعالج. لن ترسل أية بيانات أخرى عنك." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "كيلوبايت/ثانية" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "غير محدود" - -#: src/interface.py:325 -msgid "Activated" -msgstr "منشط" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "أخرى ..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "سرعة التنزيل (كيلوبايت/ثانية)" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "سرعة الرفع (كيلوبايت/ثانية)" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "دِلَج مقفل" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"دِلَج محمي بكلمة سر.\n" -"لتظهر نافذة دِلَج ، ادخل كلمة السر من فضلك" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "بلا‌نهاية" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "غير‌معروف" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "الاسم" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "المدة المتبقية حتى التمام" - -#: src/interface.py:651 -msgid "Avail." -msgstr "متاح" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "النسبة" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "اختر مسارا لنقل مصدر التورنت إليه" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "حذف مصدر التورنت القديم؟" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "تم تجميد %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "تم إدراج %s في الطابور" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "توجد إصدارة أحدث من دِلَج. أتحب أن تزور موقع التنزيل على الوب؟" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "الاتصالات" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "جدول التلبيد الموزَّع" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "دلوج" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "التنزيل" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "الرفع" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "دلوج عميل البت‌تورنت" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "اختر دليلا للتنزيل" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "حدث عطل أثناء محاولة إضافة التورنت. قد يكون الملف معطوبا." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "عطل تورنت مكرر غير معلوم." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "لا توجد مساحة شاغرة كافية على القرص لإتمام التنزيل." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "المساحة المطلوبة:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "المساحة المتاحة:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "أضف تورنت من مسار" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "أدخل مسار ملف التورنت الذي تريد تنزيله" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "تحذير - كل الملفات المنزلة من هذا التورينت سوف تحذف!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "أمتأكد أنك تريد إزالة كل التورنتات التي يجري بذرها؟" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "في الطابور" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "يجري الفحص" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "يجري الاتصال" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "يجري تنزيل البيانات الفوقية" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "يجري التنزيل" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "تم" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "يجري التخصيص" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "البايتات المطلوبة" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "لا توجد مساحة شاغرة تكفي لإتمام التنزيل." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "أُرسل الإعلان" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "الإعلان حسن" - -#: src/core.py:774 -msgid "Alert" -msgstr "تنبيه" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "شفرة إتش‌تي‌تي‌بي" - -#: src/core.py:776 -msgid "times in a row" -msgstr "الأوقات في صف" - -#: src/core.py:788 -msgid "Warning" -msgstr "تحذير" - -#: src/files.py:77 -msgid "Filename" -msgstr "اسم‌الملف" - -#: src/files.py:82 -msgid "Priority" -msgstr "الأولوية" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "مقبوس" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "مُفعّل" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "اختر ملف تورينت" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "ملفات التورينت" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "كل الملفات" - -#: src/common.py:88 -msgid "KiB" -msgstr "كيلوبايت" - -#: src/common.py:91 -msgid "MiB" -msgstr "ميجابايت" - -#: src/common.py:94 -msgid "GiB" -msgstr "جيجابايت" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "أمر خارجي" - -#: src/common.py:207 -msgid "not found" -msgstr "غير موجود" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "لا يستطيع تحميل الوصلة" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "لا يستطيع فتح ملف القائمة السوداء" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "نوع الملف خاطئ أو ملف القائمة السوداء فاسد" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "مستورد" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "أرقام ب‌إ" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "القائمة السوداء" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "المدخلات" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "وصلة القائمة السوداء" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "تحميل قائمة سوداء جديدة كل" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "الأيام" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "تحميل وتنصيب القائمة السوداء" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "استيراد" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "مكتمل" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "نسخة باطلة" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "ضع النسبة المطلوبة للتورنت." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_النسبة المطلوبة" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "النسبة المطلوبة" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"هذا يبين لك النظائر المرتبطة بكل تورنت وعنوانه,\n" -"الدولة, العميل, النسبة المكتملة وسرعة التحميل والرفع.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "عنوان ب‌إ (بروتوكول إنترنت)" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "العميل" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "النسبة المكتملة" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "صانع التورنت" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "هذا التورنت سيُصنع من ملف واحد" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "ملف:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "هذا التورنت سيُصنع من مسار" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "مجلّد:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "المصدر" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "حفظ ملف التورنت ك" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "أضف التورينت الجديد للطابور" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "ملف التورينت" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" -"Copy text \t \n" -"المتعقبون" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "التعليقات" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 كيلو بايت\n" -"64 كيلو بايت\n" -"128 كيلو بايت\n" -"256 كيلو بايت\n" -"512 كيلو بايت\n" -"1024 كيلو بايت\n" -"2048 كيلو بايت\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "حجم القطعة:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "متقدم" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_تورنت جديد" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "تورنت جديد" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "اصنع تورنت جديد" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "حدد مصدر للتورنت." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "حدد ملف لحفظ التورنت ك." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "تفضيلات الإشعار التورنت" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "فعِّل الصوت (يحتاج ل pygame, غير متوفر على وندوز)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "التورنت مكتمل" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "فعِّل سجل الملفات" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "سجل الملفات" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "النظير منِع" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "انتهى المنع" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "منع التحميل" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "تحذير المقتفي" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "إنذار المقتفي" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "إجابة المقتفي" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "ملف خطأ" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "طلب باطل" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "رسائل النظير" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "التورنت انتهى" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "حدد أحداث للتسجيل" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "حدث السجل" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "التورنت: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "رسالة النظير" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "عنوان الأيبي: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "العميل: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "سرعة النظير: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "ضع حد السرعة المطلوبة لكل تورنت." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "التورنت _سرعة التحميل" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "رفع التورنت _السرعة" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "سرعة رفع التورنت (كيلو بايت/ثانية):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "سرعة تنزيل التورنت (كيلو بايت/ثانية):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "الرسم البياني" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "المنجز" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "يوجد خطأ في محاولة بدأ الملف." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -#, fuzzy -msgid "Files" -msgstr "ملفات" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_أنقل التورنت" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "اختر مسارا لنقل الملفات إليه" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "الانتقال اكمال التحميل الى:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "المسار:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "حد التنزيل:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "حد الرفع:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "ملفات التورنت النشطة:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "فتحات الرفع:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "أقصى الإتصالات" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "الأخضر أقصى الحدود, الأصفر أدنى الحدود والأحمر متوقف" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "إذا جعِل الحد -1 فمعناه غير محدود" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "منفذ رقم" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "كلمة سر جديدة" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "كلمة سر جديدة(تأكيد)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "صورة وكتابة" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "فقط صورة" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "فقط النص" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "ترجم شيئا" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "اختر وصلة أو تورنت, ليس الإثنين معا." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "لا بيانات" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "عن" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "أضف تورنت" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "طبق" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "إنعاش تلقائي" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "حذف الملفات المحذوفة" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "عَطّل" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "محمل" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "فعِّل" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "خطأ" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "كلمة السر باطلة, أعد المحاولة" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "جمد الكل" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "أنعش الصفحة كل:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "احذف التورنت" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "استأنف الكل" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "سرعة" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "ابدأ" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "قائمة التورنت" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "الحجم الكلي" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "ارفع التورنت" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "مرفع" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "التلقيمات" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "التلقيمة" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "أدر ملحقات البحث" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "الاسم:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"أضف محرك بحث جديد بإدخال اسمه و مساره. في حقل المسار أدخل مسار صفحة البحث، و " -"سوف يعوّض عن ${query} في المسار بعبارة البحث التي يدخلها المستخدم.\n" -"مثلا، فيما ستعلق بجوجل:\n" -"الاسم: جوجل\n" -"المسار: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "مساعدة" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "عبارة البحث" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "اختر محركا" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "أدر المحركات" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "ابحث " diff --git a/po/ast.po b/po/ast.po deleted file mode 100644 index 473b912f1..000000000 --- a/po/ast.po +++ /dev/null @@ -1,2388 +0,0 @@ -# Asturian translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-21 16:25+0000\n" -"Last-Translator: Astur \n" -"Language-Team: Asturian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Amésta-y un \"Torrent\"" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Amestar" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Esanicia'l \"Torrent\"" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Esborrar" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Llimpiar" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Siguir" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pausar" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Coloca Esti \"Torrent\" delantre" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Arriba" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Coloca Esti \"Torrent\" darrera" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Abaxo" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Camudar les preferencies" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Preferencies" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugins" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Ficheru" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Amestar torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Amestar _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Llimpiar completados" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Editar" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Com_plementos" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "Vista" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Barra Ferramientes" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detáis" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "Co_lumnes" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Tamañu" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Estáu" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Collacies/os estendiendo'l archivu" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Collacies/os compartiendo" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Velocidá de descarga" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Velocidá d'unvíu" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Tiempu Restante" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Disponibilidá" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Relación de datos compartios: baxada/subida" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Aida" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Donar al Desendolcu de Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Donar" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Collacies/os estendiendo'l archivu" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Relación de datos compartios: baxada/subida" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Collacies/os compartiendo" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Peazos" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Tamañu Total" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Rastreador" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Estado'l Rastreador" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Prósimo Anunciu" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detalles" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Borra los archivos selecionaos" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Muestra / Escuende" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Añande-i un \"Torrent\"" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Llimpia Completaos na Llista" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Activa el icono del sistema na bandexa." - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimiza pa la bandexa al cerrar" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Baxada" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Xubida" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Archivos" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/bg.po b/po/bg.po deleted file mode 100644 index 078eec3e9..000000000 --- a/po/bg.po +++ /dev/null @@ -1,2580 +0,0 @@ -# Bulgarian translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-28 16:56+0000\n" -"Last-Translator: Yasen Pramatarov \n" -"Language-Team: Bulgarian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#~ msgid "Clear Finished Torrents" -#~ msgstr "Изчистване на приключилите торенти" - -#~ msgid "Maximum Download Rate:" -#~ msgstr "Максимална скорост на изтегляне:" - -#~ msgid "Maximum Upload Rate:" -#~ msgstr "Максимална скорост на качване:" - -#~ msgid "Save all downloads to:" -#~ msgstr "Запазване на всичко в:" - -#~ msgid "Downloaded this session:" -#~ msgstr "Свалени тази сесия:" - -#~ msgid "Total Downloaded:" -#~ msgstr "Общо свалени:" - -#~ msgid "Total Uploaded:" -#~ msgstr "всичко качено" - -#~ msgid "Uploaded This Session:" -#~ msgstr "качено тази сесия" - -#~ msgid "Active port:" -#~ msgstr "активен порт" - -#~ msgid "Try from:" -#~ msgstr "опитай от" - -#~ msgid "" -#~ "Are you sure you want to remove the selected torrent(s) from Deluge?" -#~ msgstr "сигурен ли си ще се изтрие избраният торент" - -#~ msgid "Add Torrent from URL" -#~ msgstr "добави торент от адрес" - -#~ msgid "Clear Completed" -#~ msgstr "изчисти завършеното" - -#~ msgid "Toolbar" -#~ msgstr "тоолбар" - -#~ msgid "Columns" -#~ msgstr "колони" - -#~ msgid "Upload Rate:" -#~ msgstr "качено съотношение" - -#~ msgid "Download Rate:" -#~ msgstr "свалено съотношение" - -#~ msgid "Estimated Time Remaining:" -#~ msgstr "Оставащо време" - -#~ msgid "Download Speed" -#~ msgstr "скорост на сваляне" - -#~ msgid "Upload Speed" -#~ msgstr "скорост на качване" - -#~ msgid "Preferences Dialog" -#~ msgstr "диалог настройки" - -#~ msgid "Ask me where to save each download" -#~ msgstr "питай ме къде да запазя сваленото" - -#~ msgid "Save Location" -#~ msgstr "място на запазване" - -#~ msgid "" -#~ "Stop seeding torrents when\n" -#~ "their share ratio reaches:" -#~ msgstr "спри да сеедваш когато сееда |nдостигне съотношение:" - -#~ msgid "to:" -#~ msgstr "към" - -#~ msgid "TCP Port" -#~ msgstr "порт" - -#~ msgid "(-1 is unlimited)" -#~ msgstr "(-1 е безлимит)" - -#~ msgid "Bandwidth " -#~ msgstr "скорост " - -#~ msgid "Error: no webbrowser found" -#~ msgstr "грешка:няма уеб браузер" - -#~ msgid "Download Rate" -#~ msgstr "свалено съотношение" - -#~ msgid "Upload Rate" -#~ msgstr "качено съотношение" - -#~ msgid "Start / Pause" -#~ msgstr "старт / пауза" - -#~ msgid "Show / Hide Window" -#~ msgstr "покажи / скрий прозореца" - -#~ msgid "Maximum Connections" -#~ msgstr "максимални връзки" - -#~ msgid "" -#~ "For some reason, the previous state could not be loaded, so a blank state " -#~ "has been loaded for you." -#~ msgstr "важно.предишната сесия не може да се заредизареди я ти" - -#~ msgid "Would you like to attempt to reload the previous session's downloads?" -#~ msgstr "искаш ли да заредиш предишната сесия" - -#~ msgid "Choose the download directory for" -#~ msgstr "избери директория за сваляне" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Добавяне на торент" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Добавяне" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Премахване на торент" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Премахване" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Изчистване на качваните торенти" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Изчистване" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Стартиране или продължаване на торент" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Продължаване" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Спиране на торент" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Спиране" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Нагоре в опашката" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Нагоре" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Надолу в опашката" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Надолу" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Промяна настройките на Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Настройки" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Приставки" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Файл" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Добавяне на торент" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Добавяне на _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Изчистване на завършените" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Редактиране" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "При_ставки" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Торент" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "П_реглед" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "Лента с _инструменти" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "По_дробности" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Колони" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Размер" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Състояние" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Качващи" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Потребители" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Скорост на сваляне" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Скорост на качване" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Оставащо време" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Наличност" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Коефицент на споделяне" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Помощ" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Дарете за разработката на програмата" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Даряване" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Страница в Интернет" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_Често задавани въпроси" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Общност" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Помощ за превода на програмата" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Превеждане на програмата..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Зареждане на помощника за първоначална настройка" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Помощник за първоначална настройка" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Изтеглено:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Качено:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Качващи:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Коефициент на споделяне:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Скорост:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Потребители:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Оставащо време:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Парчета:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Наличност:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Статистики" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Брой файлове:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Общ размер:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Следящ сървър:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Състояние на следащия сървър:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Следващо обявяване:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Име:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Път:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Данни за торента" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Подробности" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Наистина ли искате да премахнете избраните торенти " -"от Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Изтриване на свалените файлове" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Изтриване на торент-файла" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Показване/скриване" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Добавяне на торент.." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Изчистване на приключилите" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Отваряне на файл" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Избиране на всички" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Премахване избирането на всичко" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Да не се изтегля" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Обикновена" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Висока" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Най-висока" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Сливане списъците на следящи сървъри" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Торентът вече е открит в Deluge, да се слят ли списъците на следящи сървъри?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Настройки на Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Питане къде да се запазва всяко изтегляне" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Избор на папка" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Складирай всички торент-файлове в:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Запазване на изтеглянията в:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Място за изтеглянето" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Автоматично зареждане на всички торент-файлове в:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Автоматично зареждане" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Броят включени торенти, които програмата ще пуска. Задайте -1 за неограничен." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Максимален брой едновременно включени торенти:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Позволяване избирането на файлове от торентите преди зареждане" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Показване само ако торента съдържа повече от 1 файл" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Изтегляне първо на началната и крайна част на файловете" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Стартиране на торентите в спряно състояние" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Торенти" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Цялостното запълване заделя цялото място, нужно на торента за избягване на " -"фрагментация" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Цялостно запълване" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Постепенно запълване" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Използване на постепенно запълване" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Запълване" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Изтегления" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Внимание: Промените по тези настройки влизат сила чак при следващото " -"зареждане на програмата." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "От:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "До:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge автоматично ще избира всеки път различен порт." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Случайни портове" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Проверка на ползвания порт" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Използван порт:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Размяна между потребители" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Откриване на потребители в частна мрежа" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Мрежови разширения" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Входящ:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Изключено\n" -"Включено\n" -"Задължително" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Изходящ:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Предпочитано шифриране на целия поток" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Степен:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Шифриране" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Мрежа" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Преместване в края на опашката при минаване в режим на разпръскване" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Поставяне новите торенти преди приключилите в опашката" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" -"Спиране разпръскването на торенти при достигане коефициент на споделяне:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Авточатично изчистване на достигналите максимален коефициент на споделяне" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Брой часове" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Разпръскване" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Разпръскване" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Максималният брой опити за свързване за секунда. Прекалено висока стойност " -"може да предизвика срив в някой рутери. Задайте -1 за неограничен брой." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Максимум опити за свързване за секунда:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Максималният брой слотове за качване за всички торенти. Задайте -1 за " -"неограничен брой такива." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Максималната скорост на качване за всички торенти. Задайте -1 за " -"неограничена." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Максимална скорост на изтегляне за всички торенти. Задайте -1 за " -"неограничена." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Максимална скорост на изтегляне (КБ/сек):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Максимален позволен брой връзки. Задайте -1 за неограничен." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Максимален брой връзки:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Максимална скорост на качване (КБ/сек):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Максимум слотове за качване:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Максималният брой полу-отворени връзки. Прекалено висока стойност може да " -"предизвика срив в някой рутери. Задайте -1 за неограничен брой." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Максимум полу-отворени връзки:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Общо ползвана скрост" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Максимален брой връзки за торент. Задайте -1 за неограничен." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Ползвана скорост по торенти" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Скорост на връзката" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Порт" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Сървър" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Без посредник\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 с аутентикация\n" -"HTTP\n" -"HTTP с аутентикация" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Парола" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Потребителско име" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Вид на посредника" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Посредници" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Икона в системния панел" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Свиване в системния панел при затваряне" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Зареждане в системния панел" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Защита с парола на системния панел" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Парола:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Системен панел" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "Програмата ще проверява сървърите ни за по-нова своя версия." - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Съобщаване за нови версии" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Обновления" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Помогнете ни да подобрим Deluge, като ни изпращате\n" -"версиите си на Python, PyGTK, операционната ви\n" -"система и вида на процесора. Никакви други данни\n" -"няма да се изпращат." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Данни за системата" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Друго" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Про_дължаване" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "Спи_ране" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Премахване на торента" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Настройки на следящия сървър" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Обновяване на следящия сървър" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Редактиране на следящите сървъри" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_На опашка" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Най-горе" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "На_горе" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "На_долу" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "На_й-долу" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Отваряне на папката" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Показване на Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Продължаване на всички" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Спиране на всички" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Ограничение скоростта на _изтегляне" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Ограничение скоростта на _качване" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Затваряне" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Редактиране на следящите сървъри" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Редактиране на следящите сървъри" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge - избор на файл" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Торентът няма да се разпространява в мрежата без следящ сървър (DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Настройки при първо зареждане" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Този помощник ще ви помогне да настроите програмата. Ако ползвате за първи " -"път Deluge, имайте предвид, че повечето функционалности са изнесени в " -"приставки, които са достъпни от менюто Редактиране -> Приставки." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Ползване на случайни портове" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Питане къде да се запази всеки файл" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Запазване на всички изтегляния в: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Максимален брой включени торенти:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8к\n" -"56к\n" -"64к\n" -"96к\n" -"128к\n" -"192к\n" -"256к\n" -"384к\n" -"512к\n" -"640к\n" -"768к\n" -"1Mбит\n" -"2Mбита\n" -"10Mбита\n" -"20Mбита\n" -"40Mбита\n" -"50Mбита\n" -"100Mбита" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Скорост на линията ви за качване:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Помогнете ни да подобрим Deluge, като ни изпращате версиите\n" -"си на Python, PyGTK, операционната ви система и вида на процесора.\n" -"Никакви други данни няма да бъдат изпращани." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "КБ/сек" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Неограничено" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Включено" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Друго..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Скорост на изтегляне (КБ/сек):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Скорост на качване (КБ/сек):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Програмата е заключена" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge има защита с парола.\n" -"За да се покаже прозореца на Deluge, въведете паролата" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Безкрайност" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Непознат" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Име" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Оставащо време" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Наличност" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Съотношение" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "%s е спряно" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "%s е на опашка" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Има по-нова версия на програмата. Искате ли да посетите сайта за изтегляне?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Връзки" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT (децентрализирана размяна)" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Изтегляне" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Качване" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Обмен на файлове през торент (Deluge)" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Избор на папка за съхранение" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Грешка при опит за добавяне на торента. Възможно е файлът да е повреден." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Неизвестна грешка от дублиране на торент." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Няма достатъчно дисково пространство за да завърши изтеглянето." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Нужно пространство:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Налично пространство:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Добавяне на торент от URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Въведете URL на торент-файла за изтегляне" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Внимание- Всички свалени файлове на този торент ще се изтрият." - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Наистина ли искате да премахнете всички излъчвани торенти?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "На опашката" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Проверка" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Свързване" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Изтегляне на метаданни" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Изтегляне" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Готово" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Назначаване" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "байта нужни" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Няма достатъчно дисково пространство за да завърши изтеглянето." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Обявяването е изпратено" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Успешно обявяване" - -#: src/core.py:774 -msgid "Alert" -msgstr "Предупреждение" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP-код" - -#: src/core.py:776 -msgid "times in a row" -msgstr "поредни пъти" - -#: src/core.py:788 -msgid "Warning" -msgstr "Внимание" - -#: src/files.py:77 -msgid "Filename" -msgstr "Име на файл" - -#: src/files.py:82 -msgid "Priority" -msgstr "Важност" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Приставка" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Включено" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Избор на торент-файл" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Торент-файлове" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Всички файлове" - -#: src/common.py:88 -msgid "KiB" -msgstr "КБ" - -#: src/common.py:91 -msgid "MiB" -msgstr "МБ" - -#: src/common.py:94 -msgid "GiB" -msgstr "ГБ" - -#: src/common.py:97 -msgid "TiB" -msgstr "ТБ" - -#: src/common.py:99 -msgid "PiB" -msgstr "ПБ" - -#: src/common.py:206 -msgid "External command" -msgstr "Външна команда" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "IP-списък от Emule (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Грешка при изтеглянето на URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Грешка при отваряне файла с черния списък" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Грешен вид или повреден файл с черен списък" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Внесено" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP-адреси" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Черен списък" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "записа" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "дни" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Зареждане и инсталиране на черен списък" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Внасяне" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Изпълнено" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Неправилна версия" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Задаване желаното съотношение на споделяне за торент" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Желано съотношение" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Не е указано" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Не е указано" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Желано съотношение" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP-адрес" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Клиент" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Изпълнение в проценти" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Създател на торента" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Торентът ще бъде съставен от отделен файл" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Файл:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Торентът ще бъде съставен от папка" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Папка:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Източник" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Запазване на торент-файла като:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Зареждане на този торент в Deluge за разпръскване" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Добавяне на нов торент към опашката" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Торент-файл" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Следящи сървъри" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Коментари" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Автор" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 КБ\n" -"64 КБ\n" -"128 КБ\n" -"256 КБ\n" -"512 КБ\n" -"1024 КБ\n" -"2048 КБ\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Размер на частите:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Допълнително" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Приставка за създаване на торенти" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Нов торент" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Нов торент" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Създаване на нов торент" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Запазване на файла като..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Трябва да укажете източник на торента." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Трябва да изберете име на файл за запазване на торента." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Настройки на уведомленията за торентите" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Включване на мигаща икона в панела" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Премигване на иконата в панела и/или показване на съобщение при приключване " -"на торент" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Торентът е приключен" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Здраве: ОК]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Настройки за записи на събития" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Включване на журналните файлове" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Журнални файлове" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Потребителят е блокиран" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Частта е приключена" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Предупреждение от следящия сървър" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Предупреждение от следящия сървър" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Отговор от следящия сървър" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Обявление от следящия сървър" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Файлова грешка" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Невалидно запитване" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Торентът е приключен" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Избор на събития за записване" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Дневник на събитията" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "съобщение за събитие: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "торент: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "IP-адрес: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "клиент: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "код за състояние: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Поредни пъти: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Задаване на желаните ограничения на торентите" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Скорост на _изтегляне на торент" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Скорост на _качване на торент" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Скорост на качване на торент (КБ/сек):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Скорост на изтегляне на торент (КБ/сек):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Приставка за графика н амрежовата активност\n" -"\n" -"Написана от Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Графика" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Напредък" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Грешка при изпълнението на файла." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Файлове" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Преместване на торента" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Изберете папка, в която да се преместят файловете" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Преместване на приключилите изтегляния в:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL-адрес:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Ограничение за изтегляне:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Ограничение за качване:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Включени торенти:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Максимален брой връзки:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Зелени са горните лимити, жълти са долните лимити и червени са спрените" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Ако за лимит е зададено -1, той е неограничен." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Номер на порт" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Нова парола" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Нова парола (потвърждаване)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Шаблон" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Стил на бутоните" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Текст и изображения" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Само изображения" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Само текст" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Изберете адрес или торент-файл, не и двете." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "няма данни" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "обновяването трябва да е по-голямо от 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "Брой файлове" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Относно" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Добавяне на торент" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Прилагане" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Автоматично обновяване" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Наличност" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Настройка" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Изтриване на изтеглените файлове" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Изключване" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Изтеглено" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Включване" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Грешка" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Оставащо време" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Вход" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Изход" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Следващо обявяване" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Изкл." - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Паролата е неправилна, опитайте отново" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Спиране на всички" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Части" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Надолу в опашката" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Място в опашката" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Нагоре в опашката" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Повторно обявяване" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Обновяване на страницата на всеки" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Премахване на торента" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Продължаване на всички" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Задаване" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Скорост" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Стартирай" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Изпращане" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Списък с торенти" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Общ размер" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Тракер" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Статус на тракера" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Качване на торент" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Качени" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "секунди" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Емисията ще се обнови автоматично според интервала на обновяване." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Емисията ще трябва да се обнови ръчно." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Изключено" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Интервал на обновяване" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL-адрес" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Емисии" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Вид" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Емисия" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Данни" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Сезон" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Епизод" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Не съвпада" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Година" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Месец" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Ден" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Проба" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Добавяне на торента в началото на опашката" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Изтриване на филтъра при съвпадение" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Изтегляне" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Пренаписване на адресите" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Съдържанието ще се записва в подразбиращата се папка или ще се пита, ако " -"няма такава." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "По подразбиране за Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Съдържанието автоматично ще се изтегля в указаната папка." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Изберете:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Изход" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Филтри" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Показване бутон на лентата" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Интерфейс" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Нишково (изпитва се все още)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Изтегляне на емисията" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Домейн" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Път" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Стойност" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Бисквитки" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Настройка" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Управление на приставките за търсене" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Име:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Помощ" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Анонимно търсене за торенти" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Низ за търсене" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Избор на търсачка" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Управление на търсачките" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Търсене " diff --git a/po/bs.po b/po/bs.po deleted file mode 100644 index 9097093b2..000000000 --- a/po/bs.po +++ /dev/null @@ -1,2389 +0,0 @@ -# Bosnian translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-12 10:26+0000\n" -"Last-Translator: Sanel \n" -"Language-Team: Bosnian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Dodaj Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Ukloni Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -#, fuzzy -msgid "Down" -msgstr "Dolje" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Pogled" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detalji" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Kolone" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Preostalo vrijeme" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/ca.po b/po/ca.po deleted file mode 100644 index 7432bd215..000000000 --- a/po/ca.po +++ /dev/null @@ -1,2586 +0,0 @@ -# Catalan translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# Joan Duran , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-25 17:38+0000\n" -"Last-Translator: Javi Rodríguez \n" -"Language-Team: Catalan \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Afegeix un torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Afegeix" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Suprimeix un torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Suprimeix" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Neteja els torrents llavors" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Neteja" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Inicia o reprèn un torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Reprèn" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Fes una pausa a un torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pausa" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Puja el torrent de la cua" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Puja" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Baixa el torrent de la cua" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Baixa" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Canvia les preferències del Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Preferències" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Connectors" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Fitxer" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Afegeix un torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Afegeix un _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Neteja els completats" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Edita" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "_Connectors" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Visualitza" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Barra d'eines" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detalls" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Columnes" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Mida" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Estat" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Llavors" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Clients" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Velocitat de baixada" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Velocitat de pujada" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Temps restant" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Disponibilitat" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Relació de compartició" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Ajuda" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Donatius per al desenvolupament de Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Donatius" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Pàgina inicial" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_PMF" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Comunitat" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Ajuda a traduir aquesta aplicació" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Tradueix aquesta aplicació..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Executa l'assistent de configuració per primer cop" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Executa l'assistent de configuració" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Baixat:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Pujat:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Llavors:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Relació de compartició:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Velocitat:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Clients:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Temps estimat:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Peces:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Disponibilitat:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Estadístiques" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Número de fitxers:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Mida total:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Rastrejador:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Estat del rastrejador:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Següent comunicat:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nom:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Ruta:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Informació del torrent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detalls" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Segur que voleu suprimir els torrents seleccionats " -"del Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Suprimeix els fitxers baixats" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Suprimeix el fitxer .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Mostra/Oculta" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Afegeix un torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Neteja els finalitzats" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Obre un fitxer" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Selecciona-ho tot" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Desselecciona-ho tot" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "No ho baixis" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Alt" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "La més alta" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Llistes combinades de rastrejadors del Deluge" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"El torrent ja s'ha detectat en el Deluge, voleu combinar les llistes dels " -"rastrejadors?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Preferències del Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Demana on desar cada baixada" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Selecciona una carpeta" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Desa tots els fitxers torrent a:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Desa totes les baixades a:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Lloc de baixada" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Carrega automàticament tots els fitxers torrent de:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Carrega automàticament" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"El número de torrents actius que Deluge executarà. Estableix a -1 per a " -"il·limitat." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Número màxim de torrents actius simultàniament:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Habilita la selecció de fitxers torrent abans de carregar" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Només mostra si el torrent té més d'un fitxer" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" -"Prioritza les primeres i les últimes peces dels fitxers en el torrent" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Inicia els torrent en pausa" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"La màxima assignació reserva la totalitat de l'espai que necessita el " -"torrent i evita la fragmentació de disc" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Utilitza la màxima assignació" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" -"L'assignació compacta només reserva l'espai a mesura que es necessita" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Utilitza l'assignació compacta" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Assignació" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Baixades" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Nota - Els canvis per a aquestes preferències s'aplicaran la pròxima " -"vegada que el Deluge s'iniciï." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Des de:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "A:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" -"El Deluge seleccionarà automàticament un port diferent a utilitzar cada " -"vegada." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Ports aleatoris" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Comprova el port actiu" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Port actiu:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"La taula de resum distribuïda pot millorar la quantitat de connexions " -"actives." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Habilita la línia principal DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Integració automàtica universal" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "Protocol de mapatge de ports NAT" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Intercanvi de clients" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Cerca de clients locals" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Extres de xarxa" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Límit d'entrada:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Inhabilitat\n" -"Habilitat\n" -"Forçat" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Límit de sortida:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Prefereix xifrar tot el flux" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Nivell:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Negociació\n" -"Flux complet\n" -"Qualsevol" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Xifratge" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Xarxa" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Encua els torrents quan siguin llavors" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Encua els torrents nous per sobre dels finalitzats" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Atura els torrents llavors quan la relació de compartició sigui:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Neteja automàticament els torrents que arriben a la màxima relació de " -"compartició" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Parar els torrents de pujada quan el temps arribi a:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Nombre d'hores" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Netejar automàticament els torrents que arribin al temps màxim de pujada" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Llavor" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Llavor" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"El nombre màxim d'intents de connexió per segon. Un valor elevat pot trencar " -"alguns routers barats. Introdueix -1 per il·limitats intents." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Intents màxims de connexions per segon:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"El número màxim de ranures de pujada per a tots els torrents. Estableix a -1 " -"per a il·limitats." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"La velocitat màxima de pujada per a tots els torrents. Estableix a -1 per a " -"il·limitada." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"La velocitat màxima de baixada per a tots els torrents. Estableix a -1 per a " -"il·limitada." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Velocitat màxima de baixada (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" -"El número màxim de connexions permeses. Estableix a -1 per a il·limitat." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Número màxim de connexions:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Velocitat màxima de pujada (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Número màxim de ranures de pujada:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"El número màxim de connexions mig-obertes. Un valor alt pot espatllar alguns " -"routers de baix preu. Estableix a -1 per a il·limitat." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Número màxim de connexions mig-obertes:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Utilització de l'amplada de banda global" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"El número màxim de ranures de pujada per torrent. Estableix a -1 per a " -"il·limitats." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"El número màxim de connexions per torrent. Estableix a -1 per a il·limitats." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Utilització de l'amplada de banda per torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Amplada de banda" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Afecta als clients bittorrent normals" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Servidor intermediari de clients" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Servidor" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Cap\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Contrasenya" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Nom d'usuari" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Tipus de servidor intermediari" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Servidor intermediari de clients" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Rastrejador de servidors intermediaris" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Rastrejador de servidors intermediaris" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Servidor intermediari DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Servidor intermediari DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Servidor intermediari de llavors web" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Servidor intermediari de llavors web" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Servidors intermediaris" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Habilita l'icona de la safata del sistema" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimitza a la safata al tancar" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Inicia a la safata" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Protegir amb contrasenya la safata del sistema" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Contrasenya:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Safata del sistema" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Utilitza la barra de progrés avançada (utilitza lleugerament més CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Barra de progrés detallada" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"El Deluge comprovarà els servidors i us avisarà si hi ha una versió nova " -"disponible" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Avisa quan hi hagi una versió nova" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Actualitzacions" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Ajuda a millorar el Deluge enviant les versions del Pyton i PyGTK,\n" -"el sistema operatiu i el tipus de processador. No s'enviarà cap\n" -"altra informació." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Informació del sistema" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Altres" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Força la comprovació" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "_Reprèn" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pausa" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Suprimeix un torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Tracker Opcions" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Actualitza el rastrejador" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Edita els rastrejadors" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Scrape Tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Enqua" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Superior" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Puja" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Baixa" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Inferior" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Obre la carpeta contenidora" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Mostra el Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Reprèn-ho tot" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "Fes una _pausa a tot" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Límit de la velocitat de _baixada" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Límit de la velocitat de _pujada" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Surt" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Edita els rastrejadors" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Edició dels rastrejadors" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Selecció de fitxers del Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "El torrent no es distribuirà a la xarxa sense rastrejadors (DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Estableix el senyalador privat" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Configuració de la primera execució" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Aquest assistent us ajudarà a configurar el Deluge. Si sou nou al Deluge, " -"fixeu-vos que la majoria de les funcionalitats i característiques del Deluge " -"venen en forma de connectors, als quals es pot accedir fent clic a " -"Connectors en el menú Edita o en la barra d'eines." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"El Deluge necessita un rang de ports on intentarà escoltar les connexions " -"entrants. Els ports predeterminats del bittorrent són entre 6881 i 6889, tot " -"i això, la majoria de proveïdors d'Internet els bloquegen. Per aquest motiu " -"us recomanem utilitzar uns altres ports entre 49152 i 65535. " -"Alternativament, podeu deixar que el Deluge utilitzi de forma automàtica " -"ports aleatoris." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Utilitza _ports aleatoris" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Voleu que el Deluge baixi automàticament a un lloc predeterminat, o voleu " -"especificar el lloc de baixada cada cop?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Demana on desar cada fitxer" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Desa totes les baixades a: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Seleccioneu la velocitat de pujada per a la vostra connexió, que " -"s'utilitzarà per a fer suggeriments automàtics en els paràmetres de sota" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Número màxim de torrents actius:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Velocitat de pujada de la línia:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Ajuda a millorar el Deluge enviant les versions del Pyton i PyGTK,\n" -"el sistema operatiu i el tipus de processador. No s'enviarà cap\n" -"altra informació." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Incapaç de mostrar l'estat del navegador. Assegura't de tenir python-gnome2-" -"extras instal·lat o prova de configurar les variables LD_LIBRARY_PATH i " -"MOZILLA_FIVE_HOME a /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Il·limitada" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Habilitat" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Altres..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Velocitat de baixada (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Velocitat de pujada (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "El Deluge està bloquejat" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"El Deluge està protegit amb contrasenya.\n" -"Introduïu la contrasenya per a mostrar la finestra del Deluge" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infinit" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Desconegut" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nom" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Temps estimat" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Disp." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Relació" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Escollir un directori per cambiar la font del torrent" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Esborrar la font antiga del torrent?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "En pausa %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "A la cua %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Aquesta és la versió més nova del Deluge. Voleu anar al lloc de baixades?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Connexions" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Baixada" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Pujada" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Client bittorrent Deluge" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Seleccioneu un directori per a les baixades" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"S'ha produït un error mentre s'intentava afegir el torrent. És possible que " -"el fitxer .torrent sigui corrupte." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "S'ha produït un error desconegut de torrent duplicat." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "No hi ha suficient espai lliure al disc per a completar la baixada." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Espai necessari:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Espai disponible:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Afegiu un torrent des d'un URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Introduïu la URL del .torrent a baixar" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Atenció - tots els fitxers baixats d'aquest torrent seran suprimits" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Segur que voleu suprimir tots els torrents llavor?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "A la cua" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Comprovació" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Connexió" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "S'està baixant les metadades" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "S'està baixant" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Finalitzat" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "S'està destinant" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes necessaris" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "No hi ha suficient espai lliure al disc per a completar la baixada." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Comunicat enviat" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Comunicat correcte" - -#: src/core.py:774 -msgid "Alert" -msgstr "Alerta" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "Codi HTTP" - -#: src/core.py:776 -msgid "times in a row" -msgstr "cops en una fila" - -#: src/core.py:788 -msgid "Warning" -msgstr "Atenció" - -#: src/files.py:77 -msgid "Filename" -msgstr "Nom del fitxer" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioritat" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"La prioritat del fitxer només pot ser configurada quan s'utilitza la màxima " -"assignació.\n" -"Canvieu les preferències per a inhabilitar l'assignació compacte, llavors " -"suprimiu i torneu a afegir el torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Connector" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Habilitat" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"El Deluge és programari lliure, podeu redistribuir-lo i/o\n" -"modificar-lo sota els termes de la Llicència pública general\n" -"de GNU tal com publica la Free Software Foundation, tant\n" -"en la versió 2 de la llicència, o (a la vostra opció) una versió\n" -"posterior. El Deluge es distribueix amb l'esperança de que\n" -"sigui útil, però SENSE CAP GARANTIA; fins i tot sense la\n" -"garantia implícita de COMERCIALITZACIÓ o ADEQUACIÓ\n" -"A UN ÚS CONCRET. Per a més detalls vegeu la Llicència\n" -"pública general de GNU. Hauríeu d'haver rebut una còpia\n" -"de la Llicència pública general de GNU amb el Deluge, si no,\n" -"escriviu a la Free Software Foundation, Inc., 51 Franklin St,\n" -"Fifth Floor, Boston, MA 02110-1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Seleccioneu un fitxer .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Fitxers torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Tots els fitxers" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GIB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Ordre externa" - -#: src/common.py:207 -msgid "not found" -msgstr "no trobat" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Baixa i importa diverses IP de les llistes de bloqueig.\n" -"\n" -"Actualment aquest connector pot funcionar amb llistes del PeerGuardian\n" -"(binari i text), SafePeer i Emule. No estan admesos els formats de\n" -"fitxer PeerGuardian 7zip. Els fitxers poden ser especificats per URLs\n" -"o pel lloc al sistema de fitxers local.\n" -"\n" -"Una pàgina amb el punter a la llista de llocs de baixada bloquejats està\n" -"disponible al wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "Text PeerGuardian (no comprimit)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Llistat d'IPs d'Emule (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "Text SafePeer (Zip)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "No s'ha pogut baixar la URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "No es pot obrir el fitxer de la llista de bloquejats" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" -"Tipus de fitxer incorrecte o fitxer de la llista de bloquejats corromput." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importat" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Llista de bloqueig" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "entrades" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Llista de bloqueig URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Baixar una nova llista de bloquejats cada" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dies" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Carregant i instal·lant la llista de bloqueig" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "S'està important" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Completat" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "S'ha obtingut una excepció de format per al fitxer zip:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"S'està esperant un fitxer gzip, però no s'ha obtingut o potser el fitxer " -"està corromput. Editeu les preferències de la lista de bloqueig" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Líder invàlid" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Codi màgic invàlid" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Versió invàlida" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Estableix la relació desitjada per un torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "Relació _desitjada" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Sense establir" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Sense establir" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Relació desitjada" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Mostra els clients associats en cada torrent i mostra el seu IP, país, " -"client, percentatge completat i velocitats de pujada i baixada.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Adreça IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Client" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Percentatge completat" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Creador del torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Aquest torrent es formarà d'un sòl fitxer" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Fitxer:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Aquest torrent es formarà d'un directori" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Directori:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Font" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Desa el fitxer torrent com a:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Carrega aquest torrent al Deluge com a llavor" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Afegeix el torrent nou a la cua" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Fitxer torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Rastrejadors" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Llavors web" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Comentaris" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Estableix un senyalitzador privat" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Com més petita sigui la mida de les peces, més eficients seran les " -"transferències, però el «.torrent» serà més llarg" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Mida de la Peça:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Avançat" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Un connector per a crear fitxers torrent" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "Torrent _nou" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Torrent nou" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Crea un torrent nou" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Anomena i desa..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Seleccioneu una font per al torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Seleccioneu un fitxer on desar el torrent." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Preferències del notificació del torrent" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" -"Habilita l'esdeveniment sonor (necessita el pygame, no disponible en Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Habilita el parpelleig de la icona de la safata" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Habilita la notificació emergent (necessita el python-notify, no disponible " -"en Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Feu que la icona de la safata parpellegi quan s'acabi de baixar un torrent " -"i/o hi hagi una notificació emergent" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent completat" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Connector de la monitorització de la salut de la xarxa\n" -"\n" -"Escrit per Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Salut: D'acord]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Preferències del registre d'esdeveniments" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Habilita els fitxers de registre" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Fitxers de registre" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Client bloquejat" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Bloc finalitzat" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "S'està baixant el bloc" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Peça finalitzada" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "S'ha mogut l'emmagatzemament" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Avís del rastrejador" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Alerta del rastrejador" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Resposta del rastrejador" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Comunicat del rastrejador" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "S'ha produït un error de reprendre ràpidament rebutjat" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "S'ha produït un error en el bloqueig d'un client" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "S'ha produït un error en reprendre" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Fitxer erroni" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Sol·licitud invàlida" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Missatges del client" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent finalitzat" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Selecciona els esdeveniments a registrar" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Afegeix una pestanya amb el registre dels esdeveniments seleccionats.\n" -"\n" -"Els missatges d'esdeveniments provenen de les alertes libtorrent.\n" -"Si voleu que es tradueixi al vostre idioma, heu d'avisar d'aquest\n" -"problema al libtorrent, no al Deluge.\n" -"\n" -"Respecte als fitxers de registre, els registres són desats en el\n" -"directori de registres dins del directori de configuració del Deluge.\n" -"Els missatges d'esdeveniments per a torrents concrets són desats\n" -"a fitxers de registres individuals amb el mateix nom que el fitxer\n" -"associat .torrent. Els missatges d'esdeveniment que no siguin\n" -"específics a cap torrent són desats a registres anomenats\n" -"després dels esdeveniments (ex. peer_messages.log).\n" -"Els missatges d'esdeveniments en els fitxers de registre també\n" -"inclouen la data.\n" -"L'usuari és responsable de netejar els registres.\n" -"\n" -"A la versió v0.2\n" -"Els esdeveniments es tallen a la pantalla. Els fitxers de registre no es " -"tallen.\n" -"Els esdeveniments nous es visualitzen en part superior.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Registre d'esdeveniments" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "missatge d'esdeveniments: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Missatge d'un client" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "adreça ip: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "client: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "índex de la peça: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "codi d'estat: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Temps a una fila: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "índex del bloc: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "velocitat del client: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Estableix el límit de velocitat desitjat per a cada torrent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Velocitat de _baixada del torrent" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Velocitat de _pujada del torrent" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Velocitat de pujada del torrent (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Velocitat de baixada del torrent (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Connector del gràfic d'activitat de la xarxa\n" -"\n" -"Escrit per Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Gràfic" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progrés" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Ha esdevingut un error en intentar llençar el fitxer." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Aquest connector mostra els fitxers dins del torrent i us permet establir " -"les prioritats per a ells i seleccionar quins voleu o no voleu baixar.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Fitxers" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Aquest connector permet als usuaris moure el torrent a un directori diferent " -"sense haver d'esborrar i tornar a afegir el torrent. Aquesta característica " -"es pot trobar clicant sobre un torrent amb el botó dret del ratolí.\n" -"A més, permet automàticament a l'usuari tenir els torrents finalitzats " -"moguts a una carpeta diferent.\n" -"Nota: els fitxers només poden ser moguts dins la mateixa partició." - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Moure Torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Canviar La Font Del Torrent" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Selecciona un directori on moure els fitxers" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"No podeu moure un torrent a una partició diferent. Comproveu les " -"preferències. Tampoc podeu moure els fitxers torrent al mateix directori on " -"estan emmagatzemats o moure fitxers torrent abans que s'hagi creat algun " -"dels seus fitxers." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Mou les baixades completades a:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "Aquest connector permet als usuaris afegir llavors web als torrents" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Afegeix una llavor web" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Afegeix una llavor web" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Límit de baixada:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Límit de pujada:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Torrents actius:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Ranures de pujada:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Connexions màximes:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Propietats del planificador de tasques" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"El verd són els límits superior, el groc són els límits inferior i vermell " -"és aturat" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Si s'estableix un límit a -1 llavors és il·limitat." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Configuració del WebUi" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Número del port" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Contrasenya nova" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Contrasenya nova (confirmació)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Plantilla" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Estil del botó" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Plantilles de la memòria cau" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Text i imatge" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Només imatge" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Només text" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Contrasenya confirmada <> Contrasenya nova\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "tradueix alguna cosa" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Seleccioneu un URL o un torrent, no ambdós." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "sense data." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "el refresc ha de ser superior a 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "Número de fitxers" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Quant a" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Afegeix un torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Aplica" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Refresc automàtic:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Disp" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Configura" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Depurant: bolcat de dades" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Suprimeix els fitxers baixats." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Inhabilita" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Baixat" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Inhabilitat" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Error" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "T. Est." - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Inici de sessió" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Fi de sessió" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Següent comunicat" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Apagat" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "La contrasenya no és vàlida, torneu a provar-ho" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Fes una pausa a tot" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Peces" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Baixa a la cua" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "En cua la posició" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Puja a la cua" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Torna a comunicar" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Refresca la pàgina cada:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Suprimeix un torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Reprèn-ho tot" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Estableix" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Estableix el temps d'espera" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Velocitat" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Inicia" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Transmet" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Llista de torrent" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Mida total" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Rastrejador" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Estat del rastrejador" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Puja el torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Pujat" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "URL" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "segons" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"Es pot recuperar automàticament la llavor, basant-se en l'interval " -"d'actualització." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "La llavor s'ha de refrescar manualment." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Inhabilitat" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Interval d'actualització" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Llavors" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tipus" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Llavor" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informació" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Patrons" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Des de" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Temporada" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episodi" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "A través de" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Restricció històrica" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "No coincideix" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Any" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Mes" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Dia" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Prova" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Insereix el torrent a la part superior de la cua." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Estableix l'estat a en pausa." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Suprimeix el filtres quan coincideix." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Baixa" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Reemplaç" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Patró" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Torna a escriure l'enllaç" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"El contingut es desarà al directori predeterminat del Deluge, o es " -"preguntarà si no n'hi ha cap establert." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge per defecte" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "El contingut es baixarà automàticament al directori especificat." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Selecciona:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Sortida" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtres" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Mostra un icona del FlexRSS en la barra d'eines del Deluge." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Mostra el botó en la barra d'eines." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interfície" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Les llavors es recuperaran i s'analitzaran en els seus fils. L'aplicació no " -"es bloquejarà, però no és molt fiable." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "En fils (experimental)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Recupera la llavor" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domini" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Ruta" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Valor" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Galetes" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Configuració" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Configura els motors de cerca" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nom:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Afegiu un motor nou de cerca introduint el nom i l'URL. Per al nom, " -"introduïu el nom del motor de cerca que s'utilitzarà. Per a l'URL, introduïu " -"l'URL de la pàgina de cerca. La cerca del usuari substituirà qualsevol part " -"de la ${query} en l'URL.\n" -"Per exemple, una cerca al Google seria:\n" -"Nom: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Ajuda" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Buscar torrents anònimament" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Cercar una cadena" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Seleccioneu un motor" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Gestiona els motors" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Cerca " diff --git a/po/cs.po b/po/cs.po deleted file mode 100644 index cc782a288..000000000 --- a/po/cs.po +++ /dev/null @@ -1,2544 +0,0 @@ -# Czech translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-22 09:53+0000\n" -"Last-Translator: Jan Kaláb \n" -"Language-Team: Czech \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Přidat torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Přidat" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Odstranit torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Odstranit" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Vyčistit seedující torrenty" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Vyčistit" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Začít nebo obnovit torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Pokračovat" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pozastavit torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pozastavit" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Posunout dolů" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Nahoru" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Posunout nahoru" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Dolů" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Změnit nastavení Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Nastavení" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Pluginy" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Soubor" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Přidat torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "_Přidat URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Vyčistit dokončené" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Úpravy" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_giny" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "Zobra_zení" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Panel nástrojů" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Podrobnosti" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "Sloup_ce" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Velikost" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "_Stav" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Seedů" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Peerů" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Rychlost stahování" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Rychlost odesílání" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Zbývající čas" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Dostupnost" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Poměr sdílení" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Nápověda" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Přispějte na vývoj Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Přispěj" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Domovská stránka" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "Č_asto kladené otázky" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Komunita" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Pomozte přeložit tuto aplikaci" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Přeložit tuto aplikaci..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Spustí průvodce prvotním nastavením" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "Spustit p_růvodce nastavením" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Staženo:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Odesláno:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Seedů:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Poměr sdílení:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Rychlost:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Peerů:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Zbývající čas:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Dílků:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Dostupnost:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistiky" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Počet souborů:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Celková velikost:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Stav trackeru" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Příští ohlášení:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Název:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Cesta:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Informace o torrentu" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detaily" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Opravdu chcete odstranit vybrané torrenty z " -"Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Odstranit stažené soubory" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Odstranit .torrent soubor" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Zobrazit/Skrýt" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Přidat torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Odstranit dokončené" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Otevřít soubor" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Vybrat vše" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Zrušit výběr" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Nestahovat" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Střední" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Vysoká" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Nejvyšší" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge sloučení seznamů trackerů" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "Torrent již v Deluge existuje, chcete sloučit seznamy trackerů?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Nastavení Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Ptát se na cíl u každého torrentu" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Vyberte složku" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Ukládat všechny torrenty do:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Ukládat všechny torrenty do:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Cílová složka" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Automaticky nahrávat všechny torrenty v:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Autonahrát" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "Počet aktivních torrentů. Zadejte -1 pro neomezené." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maximum současně aktivních torrentů:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Povolit výběr souborů z torrentu před vložením" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Ukázat jen když má torrent víc než 1 soubor" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Upřednostňovat první a poslední kousky souborů v torrentu" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Spouštět torrenty v pozastaveném stavu" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrenty" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Plná alokace předalokuje veškerý prostor vyžadovaný torrentem a předchází " -"fragmentaci disku" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Použít plnou alokaci" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Kompaktní alokace pouze alokuje prostor podle potřeby" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Použít kompaktní alokaci" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Alokace" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Stahování" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "Prosím pozor - změny se projeví až po restartu Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Z:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Do:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge vždy vybere náhodný port." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Náhodné porty" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Vyzkoušet aktivní port" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktivní port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Distributed hash table může vylepšit množství aktivních spojení." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Povolit Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Port Mapping Protocol" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Výměna peerů" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Objevování místních peerů" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Speciality sítě" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Příchozí:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Vypnuto\n" -"Zapnuto\n" -"Vynuceno" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Odchozí:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Preferovat šifrování celého stremu" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Úroveň:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Přivítání\n" -"Celý proud\n" -"Oboje" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Šifrování" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Síť" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Zařadit torrenty na konec fronty při seedování" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Zařadit nové torrenty nad dokončené" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Zastavit seedování když poměr sdílení dosáhne:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Automaticky odstranit torrenty po dosažení maximálního poměru sdílení" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Přestat seedovat torrenty když jejich doba seedování dosáhne:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Počet hodin" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Automaticky odstranit torrenty které dosáhnou maximální doby seedování" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Seedování" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Seeduje" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Maximální počet pokusů o spojení za sekundu. Vysoké hodnoty mohou zaseknout " -"některé levné routery. Nastavte -1 pro neomezeně." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maximum pokusů o spojení za sekundu:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "Maximum odesílacích slotů. Zadejte -1 pro neomezené." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maximální rychlost odesílání pro všechny torrenty. Zadejte -1 pro neomezené." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maximální rychlost stahování pro všechny torrenty. Zadejte -1 pro neomezené." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maximální rychlost stahování (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Maximální počet povolených spojení. Zadejte -1 pro neomezené." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maximum spojení:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maximální rychlost odesílání (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maximální počet upload slotů" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Maximum polootevřených spojení. Vysoké hodnoty můžou zaseknout některé levné " -"routery. Nastavte -1 pro neomezeno." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maximum polootevřených spojení:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Celkové využití linky" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "Maximální počet upload slotů na torrent. Zadejte -1 pro neomezené." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Maximální počet spojení na torrent. Zadejte -1 pro neomezené." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Využití linky na torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Šířka pásma" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Ovlivní běžné peery bittorrentu" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Proxy peerů" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Žádný\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 s autorizací\n" -"HTTP\n" -"HTTP s autorizací" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Heslo:" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Uživatelské jméno" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Typ proxy" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Proxy peerů" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Proxy Trackeru" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Proxy trackeru" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Proxy DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Proxy DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Proxy webových seedů" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Proxy webových seedů" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxy" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Povolit ikonu" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimalizovat do ikony při zavření" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Spouštět v trayi" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Ikona chráněna heslem" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Heslo:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Ikona" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Požít pokročilý ukazatel stahování (používá tročku víc CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Detailní ukazatel stahování" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge se zkontroluje naše servery a řekne vám, když vyjde nová verze" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Informovat o nových verzích" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Aktualizace" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Pomozte nám vylepšit Deluge zasláním vaší verze PyGTK a Pythonu, operačního " -"systému a typu procesoru. Žádné další informace nejsou odesílány." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Systémové informace" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Ostatní" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Vynutit překontrolování" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Ob_novit" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pozastavit" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Odstranit torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "Možnosti _trackeru" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Obnov tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Upravit trackery" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Fronta" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Nahoře" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "Na_horu" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Dolů" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "D_ole" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Otevřít obsahující složku" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Zobrazit Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Obnovit vše" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Pozastavit vše" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Limit rychlosti _stahování" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Limit rychlosti _odesílání" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "Uk_ončit" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Upravit trackery" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Úprava trackerů" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Výběr souborů Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrent nebude distribuován na beztrackerové (DHT) síti" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Nastavit soukromý příznak" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Konfigurace prvního spuštění" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Tento průvodce vám pomůže nastavit Deluge podle svých potřeb. Pokud jste v " -"Deluge nováčkem, vězte, že většina funkcionality u Deluge je dostupná ve " -"formě zásuvných modulů, které mohou být zpřístupněny kliknutím na Zásuvné " -"moduly v nabídce Upravit nebo na nástrojové liště." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge potřebuje rozsah portů na kterých se pokusí naslouchat příchozí " -"spojení. standardní porty pro bittorrent jsou 6881-6889, avšak ty většina " -"ISP blokuje, takže doporučujeme vybrat jiné mezí 49152 a 65535. Nebo můžete " -"nechat Deluge automaticky vybrat náhodné porty." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Použít náhodné po_rty" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Chcete nechat Deluge automaticky stahovat do přednastaveného umístění nebo " -"chcete vybrat místo stahovaní vždy sami?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Ptát se kam uložit každý soubor" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Ukládat všechna stahování do: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Prosím vyberte rychlost odesílání vašeho připojení kterou poté použijeme pro " -"automatické odhadnutí voleb níže" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maximum aktivních torrentů:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "rychlost odesílání vaší linky:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Pomozte nám vylepšit Deluge odesláním Python a PyGTK\n" -"verzí, typu OS a procesoru. Žádné další\n" -"údaje nejsou odesílány." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Nelze spustit browser. Ujistěte se že máte nainstalováno python-gnome2-" -"extras nebo zkuste nastavit vaše proměnné prostředí LD_LIBRARY_PATH a " -"MOZILLA_FIVE_HOME na /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Neomezeně" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktivováno" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Další..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Rychlost stahování (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Rychlost odesílání (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge je uzamčen" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge je chráněn heslem.\n" -"Pro zobrazení okna Deluge prosím zadejte vaše heslo" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Nekonečno" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Neznámý" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Název" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Zbývající čas" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Dostupnost" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Poměr" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Vyberte kadresář kam změnit zdroj torrentu" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Smazat starý zdroj torrentu?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Pozastaveno %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Ve frontě %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "Vyšla nová verze Deluge. Chcete přejít na stránku se stažením?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Spojení" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Download" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Upload" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Bittorent klient Deluge" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Vyberte adresář pro stažení" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Nastala chyba při přidávání torrentu. Je možné že .torrent je poškozený." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Neznámá chyba duplicity torrentu." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Na disku není dost volného místa pro dokončení stahování." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Potřeba místa:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Dostupné místo:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Přidat torrent z URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Zadejte URL torrentu ke stažení" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Varování - všechny stažené soubory z tohoto torrentu budou smazány!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Jste si jisti že chcete odebrat všechny seedující torrenty?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Čeká" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Kontroluji" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Probíhá připojování" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Stahování metadat" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Stahuji" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Dokončeno" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Alokuji" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bajtů potřeba" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Není dost místa na disku pro dokončení stahování." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Ohlášení announce odesláno" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Announce OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Upozornění" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP kód" - -#: src/core.py:776 -msgid "times in a row" -msgstr "krát za sebou" - -#: src/core.py:788 -msgid "Warning" -msgstr "Varování" - -#: src/files.py:77 -msgid "Filename" -msgstr "Soubor" - -#: src/files.py:82 -msgid "Priority" -msgstr "Priorita" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Prioritu souborů lze nastavit jen při použití plné alokace.\n" -"Prosím upravte své nastavení a vypněte kompaktní alokaci, poté odstraňte a " -"opět přidejte tento torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Povolen" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge je svobodný software, můžete jej šířit a/nebo\n" -"upravovat pod podmínkami GNU General Public\n" -" License jak je publikována Free Software Foundation,\n" -"buď ve verzi 2 Licence, nebo (podle vaší volby) jakékoliv\n" -"pozdější verze. Deluge je šířen v naději, že\n" -"bude užitečný, ale BEZ JAKÉKOLIV ZÁRUKY, dokonce bez \n" -"zahrnutí záruky PRODEJNOSTI či VHODNOSTI\n" -"PRO DANÝ ÚČEL. Prohlédněte si GNU General\n" -"Public License pro více detailů. Měli byste obdržet\n" -"kopii GNU General Public License společně s\n" -"Deluge, ale pokud ne, napište Free software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Vyberte .torrent soubor" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent soubory" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Všechny soubory" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Externí příkaz" - -#: src/common.py:207 -msgid "not found" -msgstr "nenalezeno" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"stahuje a importuje ruzné IP bloklisty.\n" -"\n" -"Tento plugin zvládá PeerGuardian (binární a text).\n" -"SafePeer a Emule seznamy. PeerGuardian 7zip formát\n" -"není podporován. Soubory mohou být URL nebo lokální\n" -"soubory.\n" -"\n" -"Stránka s vodítkem na stránky s bloklisty ke stažení je\n" -"dostupná na wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian text (nekomprimovaný)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule seznam IP (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer text (zipovaný)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Nelze stáhnout URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Nelze otevřít soubor bloklistu" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Špatný typ souboru nebo poškozený seznam blokovaných." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importováno" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Bloklist" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "položek" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL bloklistu" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Stáhnout nový blocklist každý" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dny" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Načítám a instaluji bloklist" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importuji" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Hotovo" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Mám vyjímku formátu zip souboru:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Očekávali jsme gzip soubor, ale nedostali jsme ho, nebo je soubor poškozen. " -"Prosím upravte vaše nastavení Bloclistu" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Neplatná hlavička" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Neplatný kouzelný kód" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Neplatná verze" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Nastavte požadovaný poměr pro torrent" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Požadovaný poměr" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Nenastaveno" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Nenastaveno" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Požadovaný poměr" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Toto ukazuje peery spojené s každým torrentem a ukazuje jejich ip, zemi, " -"klienta, dokončených procent a rychlosti odesílání a stahování.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP adresa" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klient" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Procent dokončení" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Vytvářeč torrentů" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "tento torrent bude vytvořen z jediného souboru" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Soubor:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Tento torrent bude vytvořen z adresáře" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Adresář:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Zdroj" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Uložit torrent soubor jako:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Nahrát tento torrent do Deluge pro seedování" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Přidat nový torrent do fronty" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent soubor" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackery" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Webové seedy" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Komentáře" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Nastavit soukromý příznak" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Čím menší velikost dílku, tím efektivnější bude přenos, ale skutečná " -"velikost \".torrent\" souboru bude větší" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Velikost dílku" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Pokročilé" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Plugin pro vytváření torrentů" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Nový torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Nový torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Vytvořit nový torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Uložit soubor jako..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Musíte vybrat zdroj pro torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Musíte vybrat soubor kam uložit torrent." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Nastavení upozornění na torrent" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Zapnout zvukové upozornění (vyžaduje pygame, není dostupné na Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Povolit blikající tray ikonu" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Povolit vyskakovací upozornění (vyžaduje python-notify, nedostupné ve Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Způsobí blikání tray ikony při dokončení torrenty a/nebo vyskočení upozornění" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent dokončen" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Plugin sledování zdraví sítě\n" -"\n" -"Napsal by Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Zdraví: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Nastavení zaznamenávání událostí" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Povolit soubory záznamů" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Soubory záznamů" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Peer zablokován" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blok dokončen" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Blok stahován" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Část dokončena" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Úložiště přesunuto" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Varování trackeru" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Poplach trackeru" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Odpověď trackeru" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Oznámení trackeru" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Chyba odmítnutí rychlého dokončení" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Chyba banu peeru" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Chyba selhání hashe" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Chyba souboru" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Chybný požadavek" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Zprávy peerů" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent dokončen" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Vyberte události pro záznam" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Přidá záložku s logem vybraných událostí.\n" -"\n" -"Zprávy jsou z hlášek libtorrentu, takže pokud chcete aby tyto hlášky byly " -"přeložené, budete to muset hlásit jako chybu libtorrentu a ne Deluge.\n" -"\n" -"Logy jsou ukládány v adresáři 'log' uvnitř adresáře s konfigurací Deluge. " -"Jsou pojmenovány podle příslušného .torrent souboru. Zprávy které nepatří ke " -"konkrétnímu torrentu jsou ukládány do logu pojmenovaného podle události " -"(např.: peer_messages.log).\n" -"Zprávy v logu obsahují i čas a datum.\n" -"Uživatel je zodpovědný za číštění logů.\n" -"\n" -"Od verze 0.2\n" -"Události zobrazené v logu jsou zkracovány. Soubory logu zkracovány nejsou.\n" -"Nové události jsou nyní zobrazovány nahoře.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Záznam událostí" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "zpráva události: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Zpráva peeru" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip adresa: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "klient: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "index kousku: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "stavový kód: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Počet za sebou: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "index bloku: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "rychlost členů: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Nastaví požadované rychlostní limity pro vaše torrenty." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Rychlost _stahování torrentu" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Rychlost _odesílání torrentu" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Rychlost odesílání torrentu (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Rychlost stahování torrentu (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Plugin grafu síťové aktivity\n" -"\n" -"Napsal by Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graf" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Dokončeno" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Nastala chyba při pokusu spustit soubor." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Tento plugin ukazuje soubory uvnitř torrentu a umožňuje nastavit jim " -"prioritu a zvolit který se bude stahovat a který ne.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Soubory" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Tento plugin umožňuje uživatelům přesunout torrent do jiného adresáře aniž " -"by museli odebrat a znovu přidat torrent. Tuto možnost můžete najít pravým " -"kliknutím na torrent.\n" -"Navíc umožňuje uživatelům automaticky přesouvat stažené torrenty do jiného " -"adresáře.\n" -"Poznámka: Soubory mohou být přesouvány pouze na jednom diskovém oddílu." - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Přesunout torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "Přepnout zdroj torrentu" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Vyberte adresář pro přesun souborů" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Nemůžete přesunout torrent na jiný diskový oddíl. Prosím zkontrolujte vaše " -"nastavení. Také není možno přesunout soubory torrentu do stejného adresáře " -"kde již jsou nebo přesouvat soubory torrentu předtím něž jsou skutečně " -"vytvořeny." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Přesunout dokončená stahování do:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-zrus" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Tento plugin umožňuje uživatelům přidávat webové seedy do jejich torrentů" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "Přid_at webový seed" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Přidat webový seed" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Limit stahování:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Limit odesílání:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Aktivní torrenty:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Odesílacích slotů:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Max spojení:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Nastavení plánovače" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Zelená je vysoký limit, žlutá je spodní limit a červená je pozasrtaveno" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Pokud je limit nastaven na -1, je neomezený." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Konfigurace WebUi" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Číslo portu" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nové heslo" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Nové heslo (potvrdit)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Šablona" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Styl tlačítek" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Šablona cache" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Text a obrázky" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Jen obrázky" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Pouze text" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Potvrzené heslo se liší od nového hesla\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "něco přeložit" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Zvolte url nebo torrent, ne obojí." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "žádná data." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "obnovení musí být > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "počet souborů" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "O programu" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Přidat torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Použít" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Atomaticky obnovit:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Ava" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Nastavení" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Data Dump" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Smazat stažené soubory" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Zakázat" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Staženo" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Povolit" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Chyba" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Čas" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Přihlášení" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Odhlásit se" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Další oznámení" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Vypnuto" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Heslo je neplatné, zkuste znovu" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pozastavit vše" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Části" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Posunout dolů" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Pozice ve frontě" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Posunout nahoru nahoru" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Znovuohlásit" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Obnovit stránku každých:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Odstranit torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Obnovit vše" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Nastavit" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Nastavit odpočet" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Rychlost" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Spustit" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Odeslat" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Seznam torrentů" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Celková velikost" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Stav trackeru" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Nahrát torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Nahráno" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekundy" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Kanály budou získávány automaticky, podle intervalu aktualizace." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Kanály musí být obnoveny ručně." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Vypnuto" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Interval aktualizace" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Kanály" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Typ" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Kanál" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informace" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Vzory" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Z" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Sezóna" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Epizoda" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Skrz" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Omezení historie" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Nesouhlasí" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Rok" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Měsíc" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Den" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Vložit torrent na vrchol fronty." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Nastavit stav na pozastaveno." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Smazat filt když sedí." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Stáhnout" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Náhrada" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Vzor" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Přepisování odkazů" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Obsah bude uložen do standardního adresáře Deluge, nebo se objeví dotaz " -"pokud není uveden." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Standard Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Obsah bude automaticky stažen do daného adresáře." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Zvolte:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Výstup" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtry" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Ukazovat FlexRSS ikonu v panelu nástrojů Deluge." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Ukazovat tlačítko na panelu nástrojů." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Rozhraní" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Kanály budou získány a rozřazeny do vlastních vláken. Aplikace nebude " -"zablokována, ale může být nespolehlivá." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Vlákna (experimentální)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Získávání kanálů" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Doména" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Cesta" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Hodnota" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Sušenky" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Konfigurace" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Spravuj zásuvné moduly pro vyhledávání" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Název:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Přidejte nový vyhledávač zadáním jména a URL. Jméno zadejte jaké chcete. URL " -"zadejte tak, že ${query} bude nahrazen hledaným řetězcem.\n" -"Například Google:\n" -"Name: Google\n" -"URL: http://www.google.cz/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Nápověda" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Hledat torrenty anonymně" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Hledaný řetězec" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Vyberte vyhledávač" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Spravovat vyhledávače" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Hledat " diff --git a/po/cy.po b/po/cy.po deleted file mode 100644 index 93e0fafc5..000000000 --- a/po/cy.po +++ /dev/null @@ -1,2445 +0,0 @@ -# Welsh translation for deluge -# Copyright (c) 2008 Rosetta Contributors and Canonical Ltd 2008 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2008. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-15 16:34+0000\n" -"Last-Translator: Me \n" -"Language-Team: Welsh \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Ychwanegu Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Ychwanegu" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Tynnu Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Tynnu" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Clirio" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Dechrau neu Ail-ddechrau Torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Ail-ddechrau" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Seibio Torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Seibio" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Fyny" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Lawr" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Blaenoriaethau" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Ategion" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Ffeil" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Ychwanegu Torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Ychwanegu _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Golygu" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Golwg" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Bar Offer" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Manylion" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Colofnau" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Maint" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Statws" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Partneriaid" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Amser yn Weddill" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Argaeledd" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Cymorth" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Cyfranu tuagat ddatblygu Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Cyfranu" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Tudalen Cartref" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Cymuned" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Cyfieuthwch y rhaglen yma..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Lawrlwythwyd:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Uwchlwythwyd:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Cyflymder:" - -#: glade/delugegtk.glade:904 -#, fuzzy -msgid "Peers:" -msgstr "Cyfoedion:" - -#: glade/delugegtk.glade:925 -#, fuzzy -msgid "ETA:" -msgstr "ETA:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Darnau:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Ystadegau:" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# o ffeiliau:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Maint Llawn:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Datgan Nesa:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Enw:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Llwybr:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Gwybodaeth am Torrent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Manylion" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Dileu ffeiliau sydd wedi'w lawrlwytho." - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Dileu ffeil .torrent" - -#: glade/dgtkpopups.glade:156 -#, fuzzy -msgid "Show/Hide" -msgstr "Dangos/Cuddio" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Ychwanegwch Torrent..." - -#: glade/dgtkpopups.glade:180 -#, fuzzy -msgid "Clear Finished" -msgstr "Clirio Gorffenedig" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Agor Ffeil" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Dewis Popeth" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Datddewis Popeth" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Peidiwch a lawrlwytho" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Arferol" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Uchel" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Uchaf" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Gofyn lle i arbed pob lawrlwythiad" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Dewiswch Blygell" - -#: glade/preferences_dialog.glade:90 -#, fuzzy -msgid "Store all torrent files in:" -msgstr "Storio pob ffeil torrent yn:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -#, fuzzy -msgid "Store all downloads in:" -msgstr "Storio pob ffeil wedi'w lawrlwytho yn:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Lleoliad Lawrlwytho" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -#, fuzzy -msgid "Enable selecting files for torrents before loading" -msgstr "Galleuogwch ddewis ffeiliau ar gyfer torrents cyn yw llwytho" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -#, fuzzy -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Lawrlwythiadau" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -#, fuzzy -msgid "From:" -msgstr "Oddi wrth:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -#, fuzzy -msgid "To:" -msgstr "I:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Lefel:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Amgryptiad" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Rhwydwaith" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Nifer o oriau" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Cyflymder Lawrlwytho Cyflymaf (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -#, fuzzy -msgid "Maximum Connections:" -msgstr "Nifer mwyaf o gysulltiadau:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Ystod" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Porth" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Gwasanaethwr" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Cyfrinair" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Enw Defnyddiwr" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Cyfrinair:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -#, fuzzy -msgid "System Information" -msgstr "Gwybodaeth am y system" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Arall" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Seibio" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -#, fuzzy -msgid "_Queue" -msgstr "_Rhes" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Uchaf" - -#: glade/torrent_menu.glade:190 -#, fuzzy -msgid "_Up" -msgstr "I _Fyny" - -#: glade/torrent_menu.glade:206 -#, fuzzy -msgid "_Down" -msgstr "I _Lawr" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Gwaelod" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Seibio Popeth" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Gadael" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Digyfwng" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Arall..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Cyflymder Lawrlwytho (KiB/s)" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Anfeidroldeb" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Anhysbys" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Enw" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Cymhareb" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, fuzzy, python-format -msgid "Paused %s" -msgstr "Wedi seibio %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Cysylltiadau" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Lawrlwytho" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Lanlwytho" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Cysylltu" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -#, fuzzy -msgid "Downloading Metadata" -msgstr "Lawrlwytho Metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Llwytho i Lawr" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Wedi gorffen" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "cod HTTP" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "Rhybudd" - -#: src/files.py:77 -msgid "Filename" -msgstr "Enw Ffeil" - -#: src/files.py:82 -msgid "Priority" -msgstr "Blaenoriaeth" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Pob ffeil" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -#, fuzzy -msgid "not found" -msgstr "heb ei ddarganfod" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -#, fuzzy -msgid "entries" -msgstr "cyflawn" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "diwrnod" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Mewnforio" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Cyflawn" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Heb ei osod" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Heb ei osod" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Cyfeiriad IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -#, fuzzy -msgid "Client" -msgstr "Dibynnydd:" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Ffeil:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Ffolder:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Awdur" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Torrent Newydd" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Torrent Newydd" - -#: plugins/TorrentCreator/__init__.py:63 -#, fuzzy -msgid "Create New Torrent" -msgstr "Creu Torrent Newydd" - -#: plugins/TorrentCreator/__init__.py:99 -#, fuzzy -msgid "Save file as..." -msgstr "Dewisiadau cadw ffeil..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Log Digwyddiadau" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graff" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Cynnydd" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Ffeiliau" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Templed" - -#: plugins/WebUi/__init__.py:206 -#, fuzzy -msgid "Button Style" -msgstr "Steil Botwm" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -#, fuzzy -msgid "no data." -msgstr "dim data." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -#, fuzzy -msgid "# Of Files" -msgstr "# o Ffeiliau" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Manylion" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Gosod" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Analluogi" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Lawrlwytho" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Galluogi" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Gwall" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Mewngofnodi" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Allgofnodi" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Diffodd" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Gosod" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Cyflymder" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Cychwyn" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Cyflwyno" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Maint Cyflawn" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "eiliadau" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Crynodebau" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Math" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Gwybodaeth" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Patrymau" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Oddi wrth" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Blwyddyn" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Mis" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Diwrnod" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Prawf" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Lawrlwytho" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Amnewidiad" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Patrwm" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -#, fuzzy -msgid "Choose:" -msgstr "Dewisia:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Allbwn" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Ffiltrau" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Llwybr" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Gwerth" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Bisgedi" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -#, fuzzy -msgid "Configuration" -msgstr "Cyfluniad" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Enw:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Cymorth" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Chwilio " diff --git a/po/da.po b/po/da.po deleted file mode 100644 index 93321853e..000000000 --- a/po/da.po +++ /dev/null @@ -1,2577 +0,0 @@ -# Danish translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-23 16:12+0000\n" -"Last-Translator: Mads Peter Rommedahl \n" -"Language-Team: Danish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Tilføj torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Tilføj" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Fjern torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Fjern" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Fjern udgivende torrents" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Ryd" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Start eller fortsæt torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Fortsæt" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Sæt torrent på pause" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pause" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Skub torrent frem i køen" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Op" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Skub torrent tilbage i køen" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Ned" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Ændr Deluges indstillinger" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Indstillinger" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Udvidelsesmoduler" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Filer" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Tilføj Torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Tilføj _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Fjern Gennemførte" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Rediger" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Udvidelser" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Vis" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Værktøjslinje" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detaljer" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Kolonner" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Størrelse" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Status" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Udgivere" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Modparter" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Download-hastighed" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Upload-hastighed" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Resterende tid" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Tilgængelighed" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Delingsforhold" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Hjælp" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Donér til Deluge Development" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Donér" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Hjemmeside" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_Ofte stillede spørgsmål" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "Fællesskab" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Hjælp med at oversætte dette program" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Oversæt dette program" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Kører guiden til førstegangsopsætning" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Kør opsætningsguiden" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Hentet:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Sendt:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Udgivere:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Delingsforhold:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Hastighed" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Modparter:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Anslået Resterende Tid:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Stykker:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Tilgængelighed:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistik" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Antal Filer:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Samlet Størrelse:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Trackerstatus:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Næste Forespørgsel:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Navn:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Sti:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrent Informationer" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detaljer" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Er du sikker på, du vil fjerne de valgte " -"torrentfiler?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Slet modtagne filer" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Slet .torrent-fil" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Vis/skjul" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Tilføj torrent" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Fjern færdige torrentfiler" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Åbn fil" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Markér alle" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Fravælg alle" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Hent ikke" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Almindelig" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Høj" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Højeste" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge sammenflet trackerlister" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent findes allerede i Deluge. Vil du sammenflette tracker-listerne?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge-indstillinger" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Spørg, hvor hver fil skal gemmes" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Vælg en mappe" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Gem alle torrentfiler i:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Gem alle overførsler i:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Gemmeplacering" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Indlæs automatisk alle torrentfiler i:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Automatisk indlæsning" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Antallet af aktive torrent-filer som Deluge vil køre. Sæt til -1 for " -"ubegrænset." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Største antal samtidig aktive torrents" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Gør det muligt at vælge filer i torrents før de hentes" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Vis kun hvis torrent-filen har mere end én fil" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Giv første og sidste del af filer højere prioritet" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Start torrentfiler i pause-tilstand" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrentfiler" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Fuld tildeling tildeler al den nødvendige plads for en torrent og forhindrer " -"diskfragmentation" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Brug fuld tildeling" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" -"Kompakt tildeling bruger kun plads efterhånden som det bliver nødvendigt" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Brug kompakt tildeling" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Tildeling" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Nedhentninger" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Bemærk: Ændringer vil først blive anvendt næste gang Deluge bliver " -"genstartet." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Fra:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Til:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge vil automatisk vælge en anden port at bruge næste gang." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Tilfældige porte" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Test aktiv port" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktiv port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Distribueret hashtabel vil muligvis forbedre antallet af aktive forbindelser." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Anvend Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universel Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Port Mapping protokol" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Modpart-udveksling" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Lokal Modpart-Synlighed" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Netværksekstra" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Indgående" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Slået fra\n" -"Slået til\n" -"Tvunget" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Udgående" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Foretræk kryptering af hele datastrømmen" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Niveau:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Forhandling\n" -"Fuld strøm\n" -"Begge" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Kryptering" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Netværk" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Flyt torrentfiler til bunden af køen, når de starter med at udgive" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Sæt nye torrentfiler i køen, foran fuldendte torrents" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Stop torrent når delingsforhold har nået:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Fjern automatisk torrentfiler, der når det maksimale delingsforhold" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Stop med at udgive torrentfiler når deres udgivelsestid når:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Antal timer" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Automatisk fjernelse at torrentfiler der når deres maksimale udgivelsestid" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Udgiver" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Udgiver" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Det maksimale antal af forbindelses-forsøg per sekund. En høj værdi kan få " -"nogle svage routere til at gå ned. Sæt værdi til -1 for ubegrænset." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maksimalt antal forbindelses-forsøg per sekund:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Største antal sendepladser for alle torrentfiler. Sæt til -1 for ubegrænset." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Den højeste sendehastighed for alle torrentfiler. Sættes til -1 for " -"ubegrænset." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Den højeste nedhentningshastighed for alle torrentfiler. Sættes til -1 for " -"ubegrænset." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Højste nedhentningshastighed (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Største antal tilladte forbindelser. Sæt til 0 for ubegrænset." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Største antal forbindelser:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Højeste sendehastighed (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Højst antal sendepladser:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Det maksimale antal halvåbne forbindelser. En høj værdi kan give fejl i " -"visse billige routere. Vælg -1 for uendelig." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Højeste antal halvåbne forbindelser:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Globalt båndbreddeforbrug" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Det højeste antal sendepladser per torrent. Sæt til -1 for ubegrænset." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Det højeste antal af forbindelser per torrent. Sæt til -1 for ubegrænset." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Båndbreddeforbrug per torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Båndbredde" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Påvirker almindelige bittorrentmodparter" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Modpartsproxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Ingen\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 med Auth\n" -"HTTP\n" -"HTTP med Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Adgangskode" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Brugernavn" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxytype" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Modpartsproxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Trackerproxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Trackerproxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT-proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT-proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Netudgivelsesproxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Netudgivelsesproxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxyer" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Vis statusikon" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimer til statusområdet ved lukning" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Start i statusområde" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Beskyt statusikonet med en adgangskode" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Adgangskode:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Statusområde" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Brug det avancerede fremgangsmeter (bruger lidt mere CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Detaljeret Fremgangsmeter" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge vil tjekke vores servere og fortælle dig hvis der er en nyere version " -"tilgængelig" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Giv besked om nye versioner" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Opdateringer" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Hjælp os med at forbedre Deluge ved at sende us dine Python og PyGTK\n" -"versioner, styresystem og processortyper. Der sendes absolut \n" -"ingen anden information." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Systeminformation" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Øvrige" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Tvunget gentjek" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Fort_sæt" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pause" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Fjern torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Tracker-indstillinger" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Opdatér tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Redigér trackere" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Skrabning af Tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Kø" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Top" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Op" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Ned" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Bund" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Åbn tilhørsmappe" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Vis Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "Genoptag alle" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Paus alle" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Begrænsning af _downloadhastighed" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Begrænsning af _uploadhastighed" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Afslut" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Redigér trackere" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Trackerredigering" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge filvalg" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrent vil ikke blive distribueret på det trackerløse (DHT) netværk" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Sæt \"private\"-indikatoren" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Konfiguration ved første opstart" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Denne guide vil hjælpe dig med at tilpasse Deluge til dine ønsker. Hvis " -"dette er første gang du prøver Deluge, så bemærk at de fleste af Deluge's " -"funktioner kommer fra udvidelsesmoduler, som kan hentes ved at klikke på " -"\"Udvidelsesmoduler\" i menuen \"Rediger\" eller på værktøjslinjen." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge skal bruge en række porte som det vil tjekke for forbindelser udefra. " -"Standardportene for bittorrent er 6881-6889, men de fleste internetudbydere " -"blokerer dog disse porte, så det anbefales at du vælger nogle andre, mellem " -"49152 og 65535. Alternativt kan du få Deluge til automatisk at vælge " -"tilfældige porte for dig." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "B_rug tilfældige porte" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Ønsker du at Deluge altid automatisk skal hente filer til en bestemt " -"placering, eller vil du angive placering hver gang?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Spørg hvor hver fil skal gemmes" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Opbevar alle overførsler i: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Vælg venligst din forbindelses sendehastighed, som vi derefter vil bruge til " -"automatisk at stille forslag til indstillingerne nedenfor" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maksimalt antal aktive torrentfiler:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28,8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Udgående båndbredde:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Hjælp os med at forbedre Deluge ved at sende os dine Python og PyGTK\n" -"versioner, styresystem og processortyper. Der vil absolut\n" -"ikke blive sendt nogen anden information." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Ude af stand til at underrette browseren. Vær sikker på at du har pakken " -"python-gnome2-extras installeret eller prøv at konfigurere LD_LIBRARY_PATH " -"og MOZILLA_FIVE_HOME miljøvariablerne til /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Ubegrænset" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktiveret" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Andre ..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Downloadhastighed (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Uploadhastighed (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge er låst" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge er beskyttet med adgangskode.\n" -"Skriv venligst dit kodeord, for at vise Deluge-vinduet" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Uendelig" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Ukendt" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Navn" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Anslået tid til afslutning" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Tilgæng." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Forhold" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Vælg en mappe til at skifte torrent-kilden til" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Skal den gamle torrent-kilde slettes?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Pause %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Venter %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Der findes en nyere version af Deluge. Vil du viderestilles til vores " -"downloadside?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Forbindelser" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Modtag" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Send" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrentklient" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Vælg en mappe til modtagne filer" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"En fejl opstod under tilføjelse af torrent-filen, Det er muligt at din " -".torrent fil er beskadiget." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Ukendt dobbelt torrent fejl." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Der er ikke nok fri plads på harddisken til at færdiggøre din download." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Nødvendig diskplads:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Tilgængelig diskplads:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Tilføj torrent fra link" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Indtast linken til torrentfilen der skal hentes" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Advarsel! Alle modtagne filer for denne torrent vil blive slettet!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Er du sikker på at du vil fjerne alle færdiggjorte torrents?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Sat i kø" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Tjekker" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Forbinder" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Henter Metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Henter" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Færdig" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Allokerer" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "byte krævet" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Der er ikke nok fri diskplads til fuldføre din download" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Annoncering sendt" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Annoncering OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Advarsel" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP-kode" - -#: src/core.py:776 -msgid "times in a row" -msgstr "gange i træk" - -#: src/core.py:788 -msgid "Warning" -msgstr "Advarsel" - -#: src/files.py:77 -msgid "Filename" -msgstr "Filnavn" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioritet" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Filprioritet kan kun sættes når der bruges fuld allokering.\n" -"Du bør ændre dine indstillinger til at slå kompakt allokering fra, og " -"derefter fjerne og genåbne denne torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Udvidelsesmodul" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Slået til" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge er fri software. Du kan distribuere og/eller\n" -"ændre det, jævnfør betingelserne i GNU General Public\n" -" License, som er udgivet af Free Software Foundation,\n" -"enten version 2 af licensen, eller (hvis du ønsker det)\n" -"enhver senere version. Deluge er distribueret i håb om\n" -"at det vil være brugbart for nogen - DOG UDEN NOGEN\n" -"GARANTI for produktet. Heller ikke den medfølgende \n" -"garanti fra distributøren. Se GNU General Public\n" -"License for yderlige detaljer. Du burde have modtaget\n" -"en kopi af GNU General Public License sammen med\n" -"Deluge. Hvis ikke, bør du skrive til Free Software\n" -"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,\n" -"MA 02110 -1301 USA." - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Vælg en .torrentfil" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent-filer" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Alle filer" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Ekstern kommando" - -#: src/common.py:207 -msgid "not found" -msgstr "ikke fundet" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Henter og importer diverse IP-blocklists.\n" -"\n" -"I øjeblikket kan denne plugin håndtere PeerGuardian (binær og tekst),\n" -"SafePeer og Emule-lister. PeerGuardian 7zip-filer understøttes\n" -"ikke. Filer kan specificeres som URL eller placeringer på det lokale " -"filsystem.\n" -"\n" -"En side med henvisninger til sider hvor man kan hente blocklister kan findes " -"på wikien:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian tekst (ukomprimeret)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP list (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer tekst (zip-pakket)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Kunne ikke hente URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Kunne ikke åbne blokéringsliste-filen" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Forkert filtype eller ødelagt blokéringsliste-fil." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importeret" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPer" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blokéringsliste" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "indtastninger" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Blokéringsliste-URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Hent ny blokéringsliste hver" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dag" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Henter og installerer blokéringsliste" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importérer" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Fuldendt" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Har undtagelse for zipfiler:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Programmet forventede en gzip-fil, men fik enten ikke dette, eller også kan " -"filen være beskadiget. Ret venligst dine blokéringsliste-indstillinger" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Ugyldig leder" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Ugyldig magisk kode" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Ugyldig version" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Vælg det ønskede deleforhold for en torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Ønsket forhold" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Ikke Sat" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Ikke Sat" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Ønsket deleforhold" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Dette viser dig de modparter der er forbundet med hver torrent og viser dig " -"deres ip, land, klient, procent færdiggjort og sende/hente-hastigheder.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP-adresse" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klient" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Procent færdig" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrent-skaber" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Denne torrent vil blive lavet fra en enkelt fil" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Fil:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Denne torrent vil blive lavet fra en mappe" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Mappe:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Kilde" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Gem Torrentfil Som:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Hent denne torrent ind i Deluge til udgivelse" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Føj ny torrent til kø" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrentfil" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackere" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Web-modparter" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Kommentarer" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Forfatter" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Sæt privat-flag" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Jo mindre størrelse på stykkerne, desto mere effektiv vil overførslen være, " -"men selve \".torrent\" filen vil være større" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Stykkestørrelse:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Avanceret" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Et torrent-opretter-udvidelsesmodul" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Ny Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Ny Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Opret Ny Torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Gem fil som..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Du skal vælge en kilde til torrenten" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Du skal vælge en fil at gemme torrenten som." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Torrent påmindelsesindstillinger" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Aktiver begivenhedslyd (kræver pygame, findes ikke til Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Aktiver blinkende statusfeltikon" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Aktiver popup-påmindelse (kræver python-notify, findes ikke til Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Blink ikonet i statusfeltet når en torrent færdiggøres og/eller vis en popup" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent færdiggjort" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Netværks-sundheds-udvidelsesmodul\n" -"\n" -"Skrevet af Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Helbred: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Indstillinger for begivenhedslogning" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Aktiver logfiler" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Logfiler" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Modpart blokeret" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blok færdig" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Blok hentes" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Stump færdig" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Lager flyttet" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Tracker-advarsel" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Tracker-alarm" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Tracker-svar" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Tracker-annoncering" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "\"Hurtig genoptagelse afvist\"-fejl" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Modparts-bandlysnings-fejl" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Hash-fejl" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Fil-fejl" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Ugyldig anmodning" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Modparts-beskeder" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent'en er færdig" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Vælg begivenheden der skal føres logbog over" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Tilføjer en fane med en logbog over de valgte begivenheder.\n" -"\n" -"Begivenheds-beskeder kommer fra libtorrent-meddelelser.\n" -"Hvis du ønsker disse tekststrenge oversat til din regionaldata,\n" -"bedes du meddele problemet til libtorrent, ikke til deluge.\n" -"\n" -"Med hensyn til logbogs-filerne, bliver de gemt i en logbogs-\n" -"mappe i deluge-konfigurations-mappen. Begivenheds-\n" -"beskeder for specifikke torrenter bliver gemt i individuelle\n" -"logbogs-filer, navngivet efter den torrent-fil de er associeret\n" -"med. Begivenheds-beskeder som ikke er tilknyttet nogen\n" -"torrent-fil, bliver gemt til logbøger navngivet efter den\n" -"specifikke begivenhed (f.eks. modparts_beskeder.log).\n" -"Begivenheds-beskeder i logbogs-filer inkluderer også en\n" -"tidsstempling.\n" -"Det er brugerens ansvar at rydde op i logbogs-filerne.\n" -"\n" -"Fra og med version 0.2\n" -"Begivenhedsbeskeder bliver nu vist afkortet på skærmen, ikke i filen.\n" -"De nyeste begivenheder bliver vist øverst.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Begivenhedslog" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "begivenhedsbesked: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Modparts-besked" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip-adresse: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "klient: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "stykke-indeks: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "statuskode: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Antal gange efter hinanden: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "blokindeks: " - -#: plugins/EventLogging/tab_log.py:192 -#, fuzzy -msgid "peer speed: " -msgstr "peer hastighed " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Sæt den ønskede hastigheds-begrænsning per torrent" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrent hentehastighe_d" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrent sendehastighed" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrent sendehastighed (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrent hentehastighed (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Netværksaktivitetsgraf-udvidelsesmodul\n" -"\n" -"Skrevet af Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graf" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Fremgang" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Der opstod en fejl under forsøget på at starte filen." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Dette udvidelsesmodul viser dig filerne inde i en torrent og lader dig sætte " -"prioriteter for dem, samt vælge hvilke af dem du ønsker at hente og hvilke " -"du ikke vil have.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Filer" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Dette udvidelsesmodul giver brugeren mulighed for at flytte torrenten til en " -"anden mappe uden at skulle gentilføje torrenten. Denne funktion er " -"tilgængelig ved at højre-klikke på en torrent.\n" -"Endvidere tillader det brugeren automatisk at flytte færdige torrenter til " -"en anden mappe.\n" -"Bemærk: Filer kan, indtil videre, kun flyttes til mapper på samme partiton." - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "Flyt torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Skift Torrentkilde" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Vælg en mappe at flytte filer til" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Du kan ikke flytte en torrent til en anden partition. Tjek venligst dine " -"indstillinger. Du kan heller ikke flytte en torrent's filer til den samme " -"mappe som de allerede er i, eller flytte en torrent's filer før nogle af " -"dens filer rent faktisk er blevet oprettet." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Flyt færdige nedhentninger til:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Dette udvidelsesmodul giver brugere mulighed for at tilføje kilder fra " -"nettet til deres torrenter" - -#: plugins/WebSeed/__init__.py:51 -#, fuzzy -msgid "_Add Web Seed" -msgstr "_Tilføj Webkilde" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Tilføj Web-modpart" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "Adresse:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Download-grænse:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Upload-grænse:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Aktive torrenter:" - -#: plugins/Scheduler/plugin.py:116 -#, fuzzy -msgid "Upload Slots:" -msgstr "Upload-pladser:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Max forbindelser:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Skemaindstillinger" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "Grøn er lav begrænsning, gul er høj begrænsning og rød er stoppet" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Hvis en begrænsning er sat til -1, er denne ubegrænset." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUi Indstillinger" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Port-nummer" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Ny Adgangskode" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Ny Adgangskode(gentag)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Skabelon" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Knap-stil" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Gem skabelon" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Tekst og billede" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Kun billeder" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Kun tekst" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Bekræft Kodeordet <> Nyt kodeord\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "Oversæt noget" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Vælg en URL eller en torrent, ikke begge." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "ingen data." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "Genindlæsningen skal være >0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# Af Filerne" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Om" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Tilføj torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Anvend" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Automatisk genindlæsning:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Ava" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Konfigurere" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Data Dump" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Slet hentede filer." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Deaktiver" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Hentet" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Aktivér" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Fejl" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Eta" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Log på" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Log af" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Næste annoncering" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Deaktiver" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Kodeordet er ikke korrekt, prøv igen" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Paus alle" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Stykker" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Flyt ned i køen" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Vente-tilstand" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Flyt op i køen" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Genannoncér" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Genindlæs side hver:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Fjern torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Genoptag alle" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Definer" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Sæt tidsgrænse" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Hastighed" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Start" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Send forespørgsel" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrent-liste" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Samlet størrelse" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Trackerstatus" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Upload torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Sendt" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekunder" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"Kilde vil blive modtaget automatisk, baseret på opdaterings-intervallet." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Kilde skal opdateres manuelt." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Deaktiveret" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Opdateringsinterval" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Kilder" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Type" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Kilde" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Information" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Mønstre" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Fra" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Sæson" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episode" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Igennem" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Historie" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Er ikke ens" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "År" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Måned" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Dag" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -#, fuzzy -msgid "Insert torrent at top of queue." -msgstr "Indsæt torrenten øverst i køen" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Sæt status til Pause" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -#, fuzzy -msgid "Delete filter when matched." -msgstr "Slet filter når der er match." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Download" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Erstatning" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Mønster" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Genskriv link" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Indholdet vil blive gem i Deluges standart mappe, ellers vil en prompt komme " -"frem hvis ingen standart mappe er sat." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge standart" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Indholdet vil automatisk blive downloadet til den specifikke mappe." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Vælg:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Uddata" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtre" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Vis et FlexRSS ikon i Deluges værktøjslinje" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Vis Knap på værktøjslinjen" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Grænseflade" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Kilder vil blive modtaget og parset i deres egne tråde. Programmet vil ikke " -"blive blokeret, men det kan være ustabilt." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -#, fuzzy -msgid "Threaded (experimental)" -msgstr "Threaded (eksperimental)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Kildemodtagelse" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domæne" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Sti" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Værdi" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Indstillinger" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Håndtér søgemoduler" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Navn:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Tilføj en ny søgemaskine ved at skrive et navn og en URL. Ved Navn, skriv " -"navnet på den søgemaskine der skal bruges. Ved URL, skriv adressen på den " -"søgeside der bruges. Brugerens søgning vil erstatte alle ${query} i " -"adressen.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Hjælp" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Søg på torrents anonymt" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Søgestreng" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Vælg en motor" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Håndter motorer" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Søg " diff --git a/po/de.po b/po/de.po deleted file mode 100644 index 2cdba1513..000000000 --- a/po/de.po +++ /dev/null @@ -1,2602 +0,0 @@ -# German translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-27 21:55+0000\n" -"Last-Translator: Nightfall \n" -"Language-Team: German \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Torrent hinzufügen" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Hinzufügen" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Torrent entfernen" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Entfernen" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Entferne vollständige Downloads" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Leeren" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Download beginnen/fortsetzen" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Fortsetzen" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Download pausieren" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pausieren" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "In Warteschlange aufwärts" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Nach oben" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "In Warteschlange abwärts" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Nach unten" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Deluge-Einstellungen ändern" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Einstellungen" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Erweiterungen" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Datei" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Torrent hinzufügen" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "_URL hinzufügen" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "Fertige Torrents _entfernen" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Bearbeiten" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Erw_eiterungen" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Ansicht" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Werkzeugleiste" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Details" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Spalten" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Größe" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Status" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Seeder" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Peers" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Download" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Upload" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Verbleibende Zeit" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Verfügbarkeit" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Tauschverhältnis" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Hilfe" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Für die Deluge-Entwicklung spenden" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Spenden" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Homepage" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Gemeinschaft" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Helfen Sie, diese Anwendung zu übersetzen" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "Diese _Anwendung übersetzen..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Öffnet den Erststart-Konfigurationsassistenten" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "Sta_rte den Konfigurationsassistenten" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Heruntergeladen:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Hochgeladen:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Seeder:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Tauschverhältnis:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Geschwindigkeit:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Peers:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Verbleibend:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Teile:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Verfügbarkeit:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistiken" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Dateianzahl:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Gesamtgröße:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Tracker-Status:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Nächste Ankündigung:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Name:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Pfad:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrent-Informationen" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Details" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Möchten Sie die ausgewählten Torrents wirklich aus " -"Deluge entfernen?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Heruntergeladene Dateien löschen" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Entferne .torrent-Datei" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Ein-/Ausblenden" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Torrent hinzufügen..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Fertige Dateien entfernen" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "Datei ö_ffnen" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "_Alles auswählen" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Auswahl aufheben" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Nicht herunterladen" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normale" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Hohe" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Höchste" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge-Trackerlisten zusammenführen" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent wurde in Deluge schon gefunden. Möchten Sie die Trackerlisten " -"zusammenführen?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge-Einstellungen" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Jedes Mal nach Ort zum Speichern fragen" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Einen Ordner auswählen" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Speicherort für Torrent-Dateien:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Speichere alle Dateien in:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Download-Ziel" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Automatisch zu ladende Torrent-Dateien:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Automatisches Laden" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Die maximale Anzahl aktiver Torrents in Deluge. Auf -1 setzen für " -"unlimitiert." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Max. Anzahl gleichzeitig aktiver Torrents:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Auswahl von Dateien vor dem Herunterladen des Torrents ermöglichen" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Nur anzeigen, falls der Torrent mehr als eine Datei enthält" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Erste und letzte Stücke von Dateien in Torrents bevorzugen" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Starte Torrents pausiert" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Die volle Zuweisung belegt den gesamten Speicherplatz, der für den Torrent " -"benötigt wird, auf einmal und verhindert die Fragmentierung des Dateisystems." - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Volle Zuweisung verwenden" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" -"Die kompakte Zuweisung belegt nur soviel Speicherplatz, wie gerade benötigt " -"wird." - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Kompakte Zuweisung verwenden" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Speicherzuweisung" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Downloads" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Achtung - Diese Änderungen werden erst beim nächsten Start von Deluge " -"übernommen." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Von:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Bis:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge wählt automatisch jedes Mal einen anderen Port." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Zufällige Ports" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Aktiven Port testen" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktiver Port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Verteilte Hashtabelle (DHT) verbessert möglicherweise die Anzahl aktiver " -"Verbindungen." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Aktiviere Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universelles Plug-and-Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT-Port-Mapping-Protokoll" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -#, fuzzy -msgid "Peer Exchange" -msgstr "Peer-Austausch" - -#: glade/preferences_dialog.glade:799 -#, fuzzy -msgid "Local Peer Discovery" -msgstr "Lokale Peer-Suche" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Netzwerk-Extras" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Eingehend:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Deaktiviert\n" -"Aktiviert\n" -"Erzwungen" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Ausgehend:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Bevorzuge die Verschlüsselung des gesamten Streams" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Ebene:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Protokoll\n" -"Daten\n" -"Beides" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Verschlüsselung" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Netzwerk" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Setze fertige Torrents nach unten." - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Neue Torrents über komplettierten einreihen" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Stoppe Torrents bei einer Verteilungsrate von:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Torrents entfernen, wenn max. Tauschverhältnis erreicht" - -#: glade/preferences_dialog.glade:1105 -#, fuzzy -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Torrent anhalten nach:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Anzahl der Stunden" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Torrents welche die maximale Seeding-Dauer erreicht haben automatisch löschen" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Seede" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Die maximale Anzahl der Verbindungsversuche pro Sekunde. Ein hoher Wert " -"kann billige Router zum Absturz bringen. -1 für unlimitiert eingeben." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maximale Verbindungsversuche pro Sekunde:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Das Maximum an Upload-Slots für alle Torrents. Für keine Begrenzung auf -1 " -"setzen." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Die maximale Upload-Rate für alle Torrents. Auf -1 setzen für unendlich." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Die maximale Download-Rate für alle Torrents. Auf -1 setzen für unendlich." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maximale Download-Rate (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "max. Anzahl von Verbindungen. Setze -1 für unendlich." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "max. Verbindungen:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maximale Upload-Rate (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maximale Anzahl an Upload-Slots:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Maximale Anzahl halb-offenener Verbindungen. Eine hoher Wert könnte manche " -"Router zum Absturz bringen. (-1 für eine unbegrenzte Verbindungsanzahl.)" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maximale Anzahl halboffener Verbindungen" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Gesamte Bandbreitennutzung" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "Maximale Anzahl an Upload-Slots pro Torrent. -1 für unbegrenzt." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Maximale Anzahl an Verbindungen pro Torrent. -1 für unbegrenzt." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Bandbreite pro Torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Bandbreite" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Beeinflusst reguläre BitTorrent-Peers" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Peer-Proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Keine\n" -"SOCKSv4\n" -"SOCKSv5\n" -"SOCKSv5 mit Auth.\n" -"HTTP\n" -"HTTP mit Auth." - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Passwort" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Benutzername" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxy-Typ" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Peer-Proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Tracker-Proxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Tracker-Proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT-Proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT-Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Internet-Seed-Proxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Internet-Seed-Proxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxy-Server" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Symbol im Benachrichtigungsfeld anzeigen" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Beim Schließen in das Benachrichtigungsfeld minimieren" - -#: glade/preferences_dialog.glade:2460 -#, fuzzy -msgid "Start in tray" -msgstr "Starte im Benachrichtigungsfeld" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Schütze Benachrichtigungsfeld mit Passwort" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Passwort:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Benachrichtigungsfeld" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Benutze den erweiterten Fortschrittsbalken (benötigt ein wenig mehr CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Detaillierter Fortschrittsbalken" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge prüft, ob eine neue Versionen vorhanden ist und weist Sie " -"gegebenenfalls darauf hin." - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Über Updates informiert werden" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Updates" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Helfen Sie uns, Deluge zu verbessern, indem sie uns Ihre Python- und PyGTK-\n" -"Version sowie Betriebssystem und Prozessortyp schicken. Keine andere\n" -"Information wird übertragen." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "System-Informationen" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Sonstige" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Neue Überprüfung erzwingen" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "_Fortsetzen" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pausieren" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Entferne Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Tracker-Optionen" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "Akt_ualisiere Tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Bearbeite Tracker" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Scrape Tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Warteschlange" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Oben" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_nach oben" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Nach unten" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Unten" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Öffne beinhaltenden Ordner" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Zeige Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Alle fortsetzen" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Alle pausieren" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Maximale Downloadgeschwindigkeit" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Maximale Uploadgeschwindigkeit" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Beenden" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Bearbeite Tracker" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Tracker bearbeiten" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge-Dateiauswahl" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" -"Torrent wird nicht über das trackerlose (DHT-)Netzwerk verteilt werden." - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Setze das \"private flag\"" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Erststart-Konfiguration" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Dieser Assistent wird Ihnen helfen, Deluge ihrem Geschmack nach " -"einzurichten. Falls Sie Deluge zum ersten Mal verwenden: Beachten Sie bitte, " -"dass ein Großteil des Funktionsumfangs in Form von Erweiterungen ausgelagert " -"ist, die über die Schaltfläche \"Erweiterungen\" im \"Bearbeiten\"-Menü oder " -"in der Werkzeugleiste erreichbar sind." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge benötigt einen Bereich von Ports, auf denen eingehende Verbindungen " -"empfangen werden. Die Standard-Ports für BitTorrent sind 6881 bis 6889, " -"allerdings blockieren viele Provider diese Ports, so dass andere Variationen " -"zwischen 49152 und 65535 empfohlen werden. Alternativ kann Deluge " -"automatisch zufällige Ports auswählen." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Verwende _zufällige Ports" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Soll Deluge automatisch Dateien an einem vorbestimmten Ort speichern oder " -"soll der Ort jedes Mal manuell ausgesucht werden?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Frage für jede Datei, wo sie gespeichert werden soll." - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Speicherort für alle Downloads: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Bitte wählen Sie die Upload-Bandbreite Ihrer Internetverbindung, von der " -"ausgehend ein Vorschlag für die nachstehenden Einstellungen gemacht wird." - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maximale Anzahl aktiver Torrents:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Ihre Upload-Geschwindigkeit:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Helfen Sie uns, Deluge zu verbessern, indem Sie Ihre Python- und PyGTK-\n" -"Versionen, Betriebssystem sowie Prozessortyp an uns weiterleiten. Keine\n" -"anderen Informationen werden übermittelt." - -#: src/interface.py:235 -#, fuzzy -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Kann Browser nicht starten. Stellen Sie bitte sicher, dass python-gnome2-" -"extras installiert ist oder versuchen Sie die Umgebungsvariablen " -"LD_LIBRARY_PATH und MOZILLA_FIVE_HOME auf /usr/lib/firefox zu setzen." - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Unbegrenzt" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktiviert" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Weitere..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Download-Geschwindigkeit (KiB/s)" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Upload-Geschwindigkeit (KiB/s)" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge ist gesperrt" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge ist passwortgeschützt.\n" -"Um Deluge anzuzeigen, geben Sie bitte Ihr Passwort ein." - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Unendlich" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Unbekannt" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Name" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Verbleibende Zeit" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Verfügbar" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Verhältnis" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Neues Quellverzeichnis für die Torrentdaten wählen" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Alte Torrent-Quelle entfernen?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "%s unterbrochen" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Eingereiht %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Es gibt eine neuere Version von Deluge. Möchten Sie auf unsere Download-" -"Seite gebracht werden?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Verbindungen" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Download" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Upload" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge BitTorrent Client" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Downloadverzeichnis wählen" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Beim Hinzufügen des Torrents trat ein Fehler auf. Möglicherweise ist die " -".torrent-Datei beschädigt." - -#: src/interface.py:1422 -#, fuzzy -msgid "Unknown duplicate torrent error." -msgstr "Unbekannter \"Doppelter Torrent\"-Fehler." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Nicht genügend freier Festplattenspeicher um den Download abzuschließen." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "benötigter Speicherplatz:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "vorhandener Speicherplatz:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Torrent aus URL hinzufügen" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Geben Sie die URL des herunterzuladenden Torrents ein" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Warnung - Alle heruntergeladenen Dateien dieses Torrents werden gelöscht!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" -"Sind Sie sicher, dass Sie alle vollständigen Torrents entfernen möchten?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "In Warteschlange" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Überprüfe" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Verbindet" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Metadaten werden heruntergeladen" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Wird heruntergeladen" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Fertiggestellt" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Zuteilen" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "benötigte Bytes" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" -"Es ist nicht genügend Speicherplatz vorhanden um den Download zu beenden." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Ankündigung gesendet" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Ankündigung OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Alarm" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP-Code" - -#: src/core.py:776 -#, fuzzy -msgid "times in a row" -msgstr "mal" - -#: src/core.py:788 -msgid "Warning" -msgstr "Warnung!" - -#: src/files.py:77 -msgid "Filename" -msgstr "Dateiname" - -#: src/files.py:82 -msgid "Priority" -msgstr "Priorität" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Dateipriorität kann nur gesetzt werden, wenn der gesamte Speicherplatz " -"reserviert wurde.\n" -"Bitte ändern Sie Ihre Einstellungen und deaktivieren Sie die kompakte " -"Speicherplatzreservierung. Anschließend entfernen Sie den Torrent und fügen " -"Ihn nochmals hinzu." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Erweiterung" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Aktiviert" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge ist freie Software. Sie können es unter\n" -"den Bedingungen der GNU General Public License,\n" -"wie von der Free Software Foundation veröffentlicht,\n" -"weitergeben und/oder modifizieren, entweder gemäß\n" -"Version 2 der Lizenz oder (nach Ihrer Option) jeder\n" -"späteren Version. Die Veröffentlichung von Deluge\n" -"erfolgt in der Hoffnung, dass es Ihnen von Nutzen sein\n" -"wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne\n" -"die implizite Garantie der MARKTREIFE oder der\n" -"VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK.\n" -"Details finden Sie in der GNU General Public License.\n" -"Sie sollten ein Exemplar der GNU General Public License\n" -"zusammen mit diesem Programm erhalten haben. Falls\n" -"nicht, wenden sie sich an die Free Software Foundation\n" -"51 Franklin Street, Fifth Floor, Boston, MA 02110, USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Wählen Sie eine .torrent-Datei" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent-Dateien" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Alle Dateien" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Externer Befehl" - -#: src/common.py:207 -msgid "not found" -msgstr "nicht gefunden" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Herunterladen und Importieren von IP-Bannlisten.\n" -"\n" -"Im Moment kann dieses Plugin mit folgenden Bannlisten umgehen:\n" -"PeerGuardian (binär und Text), SafePeer und Emule.\n" -"Das 7zip-Format von PeerGuardian wird nicht unterstützt.\n" -"Die Dateien können lokal oder über eine URL angegeben werden.\n" -"\n" -"Eine Seite mit Link zu einer Bannlistensammlung ist im Deluge-Wiki\n" -"vorhanden:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (gzip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian-Text (unkomprimiert)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule-IP-Liste (gzip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer-Text (ZIP-Format)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "URL konnte nicht heruntergeladen werden" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Bannlisten-Datei konnte nicht geöffnet werden" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Falscher Dateityp oder fehlerhafte Blocklisten-Datei." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importiert" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Bannliste" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "Einträge" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Bannlisten-URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Neue Blocklist alle $ herunterladen" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "Tage" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Lade und installiere Bannliste" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importiere" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Vollständig" - -#: plugins/BlocklistImport/text.py:129 -#, fuzzy -msgid "Got format exception for zipfile:" -msgstr "Formatfehler für Zip-Datei aufgetreten:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Es wurde eine gzip-Datei erwartet aber nicht erhalten, oder vieleicht ist " -"die Datei fehlerhaft. Bitte ändern Sie Ihre Blocklisten-Einstellungen." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Ungültiger Anfang" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Ungültiger Magic-Code" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Ungültige Version" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Das gewünschte Tauschverhältnis für einen Torrent einstellen." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Gewünschtes Tauschverhältnis" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Nicht gesetzt" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Nicht gesetzt" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Gewünschtes Tauschverhältnis" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Dies zeigt die zu einem Torrent gehörenden Peers und informiert über deren " -"IP-Adresse, Land, Client, Vollständigkeit in Prozent sowie Upload- und " -"Download-Geschwindigkeiten.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP-Adresse" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Client" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Prozent komplett" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrent-Ersteller" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Dieser Torrent wird aus einer einzelnen Datei erstellt" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Datei:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Dieser Torrent wird aus einem Verzeichnis erstellt" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Verzeichnis:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Quelle" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Torrent-Datei speichern als" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Diesen Torrent zum Seeden in Deluge laden" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Füge einen Torrent der Warteliste hinzu" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent-Datei" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Tracker" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Web Seeds" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Kommentare" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Als Privat markieren" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Je kleiner die Stückgröße ist, desto effizienter wird der Dateitransfer " -"sein, allerdings wird die \".torrent\"-Datei größer sein." - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Stückgröße:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Erweitert" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Eine Erweiterung zum Erstellen von Torrents" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Neuer Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Neuer Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Erstelle neuen Torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Datei speichern unter..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Sie müssen eine Quelle für den Torrent auswählen." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" -"Sie müssen eine Datei auswählen, in der Sie den Torrent speichern möchten." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Torrent-Benachrichtigungseinstellungen" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" -"Ereigniston aktivieren (benötigt pygame, unter Win32 nicht verfügbar)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Aktiviere blinkendes Tray-Symbol" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Popup-Benachrichtigungen anzeigen (benötigt python-notifiy; nicht verfügbar " -"für Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Wenn ein Torrent komplett ist, lasse das Tray-Symbol blinken und/oder eine " -"Popup-Benachrichtigung erscheinen" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent fertig" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Erweiterung zur Überwachung des Verbindungsstatus\n" -"\n" -"Geschrieben von Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Verbindung: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Ereignisprotokoll-Einstellungen" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Aktiviere Protokolldateien" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Protokolldateien" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Peer gebannt" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Block wurde geladen" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Block wird heruntergeladen" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Teil komplett" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Speicherort verändert" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Tracker-Warnung" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Tracker-Alarm" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Tracker-Antwort" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Tracker-Ankündigung" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Fehler: Schnellfortsetzung abgewiesen" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Peer-Bann-Fehler" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Fehler: Hash fehlgeschlagen" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Dateifehler" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Ungültige Anfrage" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Peer-Nachrichten" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent fertig" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Wähle zu protokollierende Ereignisse" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Fügt einen Reiter mit einem Protokoll ausgewählter Ereignisse hinzu.\n" -"\n" -"Ereignisnachrichten stammen aus libtorrent-Warnungen.\n" -"Wenn Sie die Nachrichten in Ihre Sprache übersetzt sehen möchten, müssen " -"Sie\n" -"dies an libtorrent und nicht an deluge melden.\n" -"\n" -"Die Protokolldateien werden in einem Unterverzeichnis des deluge-\n" -"-Konfigurationserzeichnisses abgelegt. Ereignisnachrichten für bestimmte " -"Torrents\n" -"werden in separate Protokolldateien gespeichert welche nach der .torrent-\n" -"Datei benannt sind. Ereignisnachrichten, die nicht zu einem Torrent " -"gehören,\n" -"werden dem Nachrichtentyp entsprechend abgespeichert (z. B. peer-" -"messages.log).\n" -"Ereignisnachrichten in den Protokolldateien haben jeweils einen " -"Zeitstempel.\n" -"Der Benutzer ist dafür verantwortlich, die Protokolle zu säubern.\n" -"\n" -"Ab Version 0.2:\n" -"Ereignisnachrichten werden jetzt auf den Bildschirm zurechtgeschnitten, die\n" -"Protokolldateien aber nicht.\n" -"Neue Nachrichten werden oben angezeigt.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Ereignisprotokoll" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "Ereignisnachricht: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "Torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Peer-Nachricht" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "IP-Adresse: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "Client: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "Teilindex: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "Statuscode: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Anzahl: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "Blockindex: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "Peer-Geschwindkeit: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" -"Die gewünschte Geschwindigkeitsbegrenzung für einen Torrent einstellen." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrent-_Downloadgeschwindigkeit" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrent-Upload_geschwindigkeit" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrent-Uploadgeschwindigkeit (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrent-Downloadgeschwindigkeit (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Erweiterung zum Anzeigen der Netzwerkaktivität\n" -"\n" -"Geschrieben von Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Diagramm" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Fortschritt" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Es ist ein Fehler beim Aufrufen der Datei aufgetreten." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Diese Erweiterung zeigt Ihnen die Dateien innerhalb eines Torrents und " -"erlaubt Ihnen, Prioritäten zu setzen sowie auszuwählen, welche Dateien " -"heruntergeladen werden sollen und welche nicht.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Dateien" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Diese Erweiterung ermöglicht Benutzern einen Torrent in ein anderes " -"Verzeichnis zu verschieben, ohne den Torrent enfernen und wieder hinzufügen " -"zu müssen. Auf diese Funktion können Sie mit einem Rechtsklick auf einen " -"Torrent zugreifen.\n" -"Des weiteren erlaubt sie, fertige Torrents automatisch in einen anderen " -"Ordner verschieben zu lassen.\n" -"Hinweis: Dateien können derzeitig nur innerhalb der gleichen Partition " -"verschoben werden." - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Verschiebe Torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "Torrent-Quelle _wechseln" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Wähle den Zielordner für das Verschieben" - -#: plugins/MoveTorrent/__init__.py:133 -#, fuzzy -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Sie können den Torrent nicht auf eine andere Partition verschieben. Bitte " -"überprüfen Sie die Einstellungen. Sie können außerdem weder Torrent-Dateien " -"in ein Verzeichnis verschieben in dem sie bereits sind, noch können Sie sie " -"verschieben wenn sie noch nicht wirklich erstellt worden sind." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Abgeschlossene Downloads verschieben nach:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "Abbrechen" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "OK" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Diese Erweiterung gibt dem Benutzer die Möglichkeit, Web-Seeds zu einem " -"Torrent hinzuzufügen." - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Füge Web-Seed hinzu" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Füge Web-Seed hinzu" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Download limitierung" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Upload Limitierung" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Aktive Torrents" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Upload Slots:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Max Verbindungen" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Zeitplaner Einstellungen" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Grün sind die hohen Limits, gelb sind die niedrigen Limits und rot ist " -"gestoppt." - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Wenn ein Limit auf -1 steht, ist es unlimitiert." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUi Konfiguration" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Port Nummer" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Neues Passwort" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Neues Passwort(Bestätigung)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Template" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Button Style" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Template zwischenspeichern" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Text und Bild" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Nur Bild" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Nur Text" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Bestätigtes Passwort <> Neues Passwort\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "übersetze etwas" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Wähle eine URL oder einen Torrent, nicht beides." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "Keine Daten." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "Refresh muss > 0 sein" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# an Dateien:" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Über" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Torrent hinzufügen" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Übernehmen" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Automatische Aktualisierung:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Ava" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Konfiguration" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Stack speichern" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Lösche heruntergeladene Dateien." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Deaktivieren" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Heruntergeladen" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Aktivieren" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Fehler" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Verbleibend" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Anmeldung" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Abmelden" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Nächster Announce" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Aus" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Passwort ist ungültig. Versuche es nochmal." - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Alle anhalten" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Teile" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "In der Warteschlange nach Unten" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Warteschlangen-Positition" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "In der Warteschlange nach Oben" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Manueller Announce" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Lade Seite neu alle:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Torrent entfernen" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Alle fortsetzen" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Setzen" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Setze Timeout" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Geschwindigkeit:" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Start" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Eintragen" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrentliste" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Gesamtgröße" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Tracker-Status" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Torrent Hochladen" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Hochgeladen" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "URL" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "Sekunden" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"Feed wird basierend auf dem Aktualisierungs-Intervall automatisch empfangen." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Feed muss manuell aktualisiert werden." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Deaktivert" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Aktualisierungs Intervall" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feeds" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Art" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Information" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Erkennungsmuster" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Von" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Staffel" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episode" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Nach" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Verlaufs Beschränkung" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Keine Übereinstimmung" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Jahr" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Monat" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Tag" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Torrent zum Anfang der Warteschlange hinzufügen." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Setze Zustand auf pausiert" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Lösche Filter nach Übereinstimmung" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Download" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Ersetzen durch" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Muster" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Link Ersetzung" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Inhalt wird in Deluge's standard Verzeichnis gespeichert, oder ein Fenster " -"wird erscheinen wenn kein Verzeichnis definiert ist." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge standard" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" -"Inhalt wird automatisch in das ausgewählte Verzeichnis Heruntergeladen." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Auswählen:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Ausgabe" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filter" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Zeige ein FlexRSS Symbol in Deluge's Menüleiste" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Zeige Button in Menüleiste" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Oberfläche" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Feeds werden in eigenen Instanzen heruntergeladen und analysiert. Die " -"Anwendung wird nicht blockiert, es kann aber unzuverlässig sein." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Mit mehreren Threads (experimentell)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Feed Abfrage" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domain" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Pfad" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Wert" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Einstellungen" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Erweiterungen für die Suche verwalten" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Name:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Füge eine neue Suchmaschine hinzu, indem du Name und URL angibst. Die " -"Suchanfrage wird an die Stelle von ${query} in die URL gesetzt. \n" -"Beispiel für eine Google-Suchanfrage:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Hilfe" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Anonym nach Torrents suchen" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Suchbegriff" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Wähle eine Suchmaschine" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Suchmaschinen verwalten" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Suche " diff --git a/po/el.po b/po/el.po deleted file mode 100644 index ac200541f..000000000 --- a/po/el.po +++ /dev/null @@ -1,2600 +0,0 @@ -# Greek, Modern (1453-) translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-07 17:43+0000\n" -"Last-Translator: Michalis \n" -"Language-Team: Greek, Modern (1453-) \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Προσθήκη Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Προσθήκη" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Αφαίρεση Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Αφαίρεση" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Αφαίρεση torrents που διαμοιράζονται" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Καθαρισμός" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Εκκίνηση ή Συνέχιση του Torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Συνέχιση" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Παύση του Torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Παύση" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Μετακινήστε το torrent ψηλότερα στην σειρά αναμονής" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Πάνω" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Μετακινήστε το torrent χαμηλότερα στην σειρά αναμονής" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Κάτω" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Αλλαγή Προτιμήσεων του Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Προτιμήσεις" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Πρόσθετα" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Αρχείο" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Προσθήκη Τόρρεντ" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Προσθήκη _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Καθαρισμός Ολοκληρωμένων" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Επεξεργασία" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_gins" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Προβολή" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Γραμμή Εργαλείων" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Λεπτομέρειες" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Στήλες" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Μέγεθος" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Κατάσταση" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Διαμοιραστές" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Συνδέσεις" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Ταχύτητα λήψης" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Ταχύτητα αποστολής" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Χρόνος που απομένει" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Διαθεσιμότητα" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Αναλογία διαμοιρασμού" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Βοήθεια" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Προσφέρετε χρήματα στην ανάπτυξη του Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Προσφέρετε χρήματα" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Αρχική Σελίδα" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_Συχνές ερωτήσεις" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Κοινότητα" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Βοηθείστε να μεταφραστεί αυτή η εφαρμογή" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Μεταφράστε αυτην την εφαρμογή" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Εκτελεί τον οδηγό αρχικών ρυθμίσεων" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Εκτέλεση Οδηγού Ρυθμίσεων" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Έχουν ληφθεί:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Έχουν αποσταλεί:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Χρήστες που διανέμουν:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Αναλογία Διαμοιρασμού" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Ταχύτητα:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Υπολογιστές:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Υπόλοιπος χρόνος λήψης" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Κομμάτια" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Διαθεσιμότητα:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Στατιστικά" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# από τα αρχεία:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Συνολικό Μέγεθος" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Ιχνηλάτης" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Κατάσταση Ιχνηλάτη" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Επόμενη ανακοίνωση" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Όνομα:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Διαδρομή:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Πληροφορίες Torrent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Λεπτομέρειες" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Σίγουρα θέλετε να αφαιρεθούν το/τα επιλεγμένο/-α " -"torrent(s) από το Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Διαγραφή των αρχείων που έχουν κατέβει" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Διαγραφή .torrent αρχείου" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Εμφάνιση/Απόκρυψη" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Προσθήκη Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Καθάρισε τα ολοκληρωμένα" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Άνοιγμα Αρχείου" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Επιλογή Όλων" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Αποεπιλογή ;Oλων" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Να μήν ληφθεί" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Κανονικό" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Υψηλό" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Υψηλότερο" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Συγχώνευση καταλόγων ιχνηλατών του Deluge" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Βρέθηκε ίδιο torrent στο Deluge,θα θέλατε συγχώνευση των καταλόγων ιχνηλατών?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Προτιμίσεις Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Ερώτηση για την τοποθεσία αποθήκευσης κάθε λήψης" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Επιλέξτε ένα φάκελο" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Αποθήκευση όλων των αρχείων torrent σε" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Αποθήκευση όλων των ληφθέντων αρχείων στο:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Τοποθεσία Λήψης" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Αυτόματη μεταφόρτωση όλων των αρχείων του torrent σε" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Αυτόματη μεταφόρτωση" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "Ο μέγιστος αριθμός ενεργών torrents. -1 για απεριόριστα." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Μέγιστος αριθμός ταυτόχρονα ενεργών torrents:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Ενεργοποίηση επιλογής αρχείων για τα torrents πρίν την λήψη" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Προβολή μόνο αν το torrent έχει περισσότερα του ενός αρχεία" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" -"Να δοθεί προτεραιότητα στα πρώτα και τα τελευταία τμήματα αρχείων αυτού του " -"torrent." - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Εκκίνηση torrent σε κατάσταση παύσης" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrent" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Η πλήρης ανάθεση χώρου στο δίσκο αναθέτει εκ των προτέρων όλο τον απαραίτητο " -"χώρο στο torrent και αποτρέπει τον κατακερματισμό του δίσκου" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Χρήση Πλήρους Ανάθεσης Χώρου" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" -"Η συμπαγής ανάθεση χώρου στο δίσκου αναθέτει στο torrent μόνο τον απαραίτητο " -"σε κάθε στιγμή χώρο." - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Χρήση Συμπαγούς Ανάθεσης Χώρου" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Ανάθεση Χώρου" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Λήψεις" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Προσοχη - Οι αλλαγές σε αυτές τις ρυθμίσεις θα εφαρμοστούν μετά την " -"επόμενη εκκίνηση του Deluge" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Από:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Έως:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Το Deluge θα επιλέγει αυτόματα διαφορετική θύρα κάθε φορά." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Τυχαίες θύρες" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Έλεγχος Ενεργής Θύρας" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Ενεργή Θύρα:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Ο κατανεμημένος πίνακας hash (DHT) πιθανώς να βελτιώσει τον αριθμό των " -"ενεργών συνδέσεων." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Ενεργοποίηση του Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "Πρωτόκολλο Αντιστοίχισης Θυρών NAT" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Ανταλλαγή μεταξύ υπολογιστών" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Εντοπισμός τοπικών υπολογιστών" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Επιπλέον Ρυθμίσεις Δικτύου" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Εισερχόμενα:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Απενεργοποιημένη\n" -"Ενεργοποιημένη\n" -"Υποχρεωτική" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Εξερχόμενα:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Προτίμηση κρυπτογράφησης όλων των δεδομένων" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Επίπεδο:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr " Κρυπτογράφηση " - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Δίκτυο" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" -"Προσθήκη των torrent που ολοκληρώθηκαν και διαμοιράζονται στο τέλος της ουράς" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Προσθήκη νέων torrents πάνω από τα ολοκληρωμένα" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" -"Διακοπή του διαμοιρασμού των torrent όταν η αναλογία διαμοιρασμού φτάσει:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Αυτόματος καθαρισμός των torrent όταν φτάσουν τη μέγιστη αναλογία " -"διαμοιρασμού" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" -"Διακοπή διαμοιρασμού torrents όταν ο χρόνος διαμοιρασμού τους φτάσει:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Αριθμός ωρών" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Αυτόματη εκκαθάριση torrents που φτάνουν το μέγιστο χρόνο διαμοιρασμού" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Διαμοιρασμός" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Διμοιρασμός" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Ο μέγιστος αριθμός προσπαθειών σύνδεσης ανά δευτερόλεπτο. Μεγάλες τιμές εδώ " -"μπορεί να κολλήσουν καποιους φθηνούς δρομολογητές (routers). -1 για " -"απεριόριστες." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Μέγιστος αριθμός προσπαθειών σύνδεσης ανά δευτερόλεπτο." - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Ο μέγιστος αριθμός θυρίδων αποστολής για όλα τα torrents. Ορίστε -1 για " -"απεριόριστες." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Η μέγιστη ταχύτητα αποστολής για όλα τα torrents. -1 για απεριόριστη." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Η μέγιστη ταχύτητα λήψης για όλα τα torrents. Ορίστε -1 για απεριόριστη." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Μέγιστη Ταχύτητα Λήψης (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Το μέγιστο επιτρεπτό πλήθος συνδέσεων. -1 για απεριόριστο." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Μέγιστο πλήθος συνδέσεων" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Μέγιστη Ταχύτητα Αποστολής (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Μέγιστος Αριθμός Θυρίδων Αποστολής:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Το μέγιστο πλήθος ημι-ανοιχτών συνδέσεων. Μία υψηλή τιμή μπορεί να " -"προκαλέσει την κατάρρευση κάποιων φθηνών δρομολογητών. Θέστε -1 για " -"απεριόριστες συνδέσεις." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Μέγιστο πλήθος ημι-ανοιχτών συνδέσεων:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Συνολική χρήση εύρους δικτύου" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Ο μέγιστος αριθμός θυρίδων αποστολής ανά torrent. Ορίστε -1 για απεριόριστες." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Ο μέγιστος αριθμός συνδέσεων ανά torrent. Ορίστε -1 για απεριόριστες." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Ανά Torrent Χρήση Εύρους Ζώνης" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Εύρος Ζώνης" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Επηρεάζει τις κανονικές συνδέσεις bittorrent" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Διαμεσολαβητής συνδέσεων" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Θύρα" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Εξυπηρετητής" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Κανένα\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Κωδικός Χρήστη" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Όνομα Χρήστη" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Τύπος διαμεσολαβητή" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Διαμεσολαβητής Συνδέσεων" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Διαμεσολαβητής Ιχνηλάτη" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Διαμεσολαβητής Ιχνηλάτη" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Διαμεσολαβητής DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Διαμεσολαβητής DHT" - -#: glade/preferences_dialog.glade:2205 -#, fuzzy -msgid "Web Seed Proxy" -msgstr "Διαμεσολαβητής Web Seed" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Διαμεσολαβητής Web Seed" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Διαμεσολαβητές" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Εικονίδιο στη μπάρα συστήματος" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Ελαχιστοποίηση στην υποδοχή κατά την έξοδο" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Εκκίνηση στην μπάρα συστήματος" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Προστασία μεγιστοποίησης από την μπάρα με κωδικό" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Κωδικός πρόσβασης:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Υποδοχή συστήματος" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Χρήση της προηγμένης γραμμής προόδου (χρησιμοποιεί ελαφρώς περισσότερη " -"επεξεργαστική ισχύς και μνήμη)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Λεπτομερής μπάρα προόδου" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Το Deluge θα ελέγχει τους εξυπηρετητές μας και θα σας ενημερώνει εάν υπάρχει " -"νεότερη διαθέσιμη έκδοση" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Ενημέρωση για νέες εκδόσεις" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Ενημερώσεις" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Βοηθήστε μας να βελτιώσουμε το Deluge στέλνοντας τις\n" -"εκδόσεις Python και PyGTK που χρησιμοποιείτε, καθώς και\n" -"τους τύπους λειτουργικού και επεξεργαστή σας. Καμία\n" -"άλλη πληροφορία δεν πρόκειται να σταλεί." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Πληροφορίες Συστήματος" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Άλλο" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Άμεσος Επανέλεγχος" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Συ_νέχεια" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Παύση" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Αφαίρεση Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Ενημέρωση Ιχνηλάτη" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Επεξεργασία Ιχνηλατών" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Τοποθέτηση στην ουρά" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Κορυφή" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Πάνω" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Κάτω" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Κάτω" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Άνοιγμα του Περιέχοντος Φακέλου" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Εμφάνιση Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Συνέχιση Όλων" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Παύση Όλων" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Όριο Ταχύτητας _Κατεβάσματος" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Όριο Ταχύτητας _Ανεβάσματος" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_'Εξοδος" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Επεξεργασία Ιχνηλατών" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Επεξεργασία Ιχνηλατών" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Επιλογή Αρχείου Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Το torrent δεν θα διαμοιρασθεί στο δίκτυο άνευ ιχνηλάτη (DHT)." - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Ορισμός σημαίας ιδιωτικού" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Ρύθμιση κατά την Πρώτη Εκτέλεση" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Αυτός ο οδηγός θα σας βοηθήσει να ρυθμίσετε το Deluge κατά τις επιθυμίες " -"σας. Εάν είστε νέος χρήστης του Deluge, παρακαλώ σημειώστε ότι το μεγαλύτερο " -"μέρος των δυνατοτήτων και των χαρακτηριστικών του Deluge έρχεται από τα " -"Plugs, τα οποία μπορούν να ρυθμιστούν πατώντας στο μενού Επεξεργασία -> " -"Plugins ή μέσω της γραμμής εργαλείων." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Το Deluge χρειάζεται ένα εύρος θυρών στις οποίες θα προσπαθεί να ανιχνεύει " -"εισερχόμενες συνδέσεις. Στο bittorrent συνήθως χρησιμοποιούνται εξ ορισμού " -"οι θύρες 6881-6889, όμως οι περισσότεροι πάροχοι διαδικτύου εμποδίζουν τη " -"χρήση αυτών των θυρών, και για αυτό είναι προτιμότερο να επιλέξετε άλλες " -"θύρες, από την 49152 έως την 65535. Εναλλακτικά, μπορείτε να επιλέξετε την " -"αυτόματη επιλογή τυχαίων αριθμών θυρών από το Deluge." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Χρύση _Τυχαίων Θυρών" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Επιθυμείτε το Deluge να αποθηκεύει τα αρχεία σε μια προεπιλεγμένη τοποθεσία, " -"ή προτιμάτε να ορίζετε την τοποθεσία αποθήκευσης κάθε φορά εσείς;" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Ερώτηση για την τοποθεσία αποθήκευσης κάθε αρχείου" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Αποθήκευση όλων των αρχείων στο: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Παρακαλώ επιλέξτε την ταχύτητα αποστολής της σύνδεσής σας, η οποία θα " -"χρησιμοποιηθεί ώστε να προταθούν κάποιες αυτοματοποιημένες τιμές στις " -"παρακάτω ρυθμίσεις." - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Μέγιστος Αριθμώς Ενεργών Torrents:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Η Ταχύτητα Αποστολής της Γραμμής σας" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Βοηθήστε μας να βελτιώσουμε το Deluge στέλνοντάς μας τις\n" -"εκδόσεις Python και PyGTK που χρησιμοποιείτε, καθώς και τους\n" -"τύπους λειτουργικού συστήματος και επεξεργαστή. Καμία άλλη \n" -"πληροφορία δεν πρόκειται να σταλεί." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Είναι αδύνατο να εντοπιστή ο φυλλομετρητής. Βεβαιωθείτε ότι έχετε " -"εγκαταστήσει το πακέτο python-gnome2-extras ή δοκιμάστε να θέσετε τις " -"μεταβλητές LD_LIBRARY_PATH και MOZILLA_FIVE_HOME στην τιμή /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Χωρίς περιορισμό" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Ενεργοποιημένο" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Άλλο..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Ταχύττητα Λήψης (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Ταχύτητα Αποστολής (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Το Deluge είναι κλειδωμένο" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Το Deluge προστατεύται με κωδικό.\n" -"Για να εμφανίσετε το παράθυρο του Deluge, παρακαλούμε εισάγετε τον κωδικό σας" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Άπειρο" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Άγνωστο" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Όνομα" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Εκτιμ. Χρ. Αναμονής" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Διαθέσ." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Αναλογία" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Παύση %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Σε ουρά %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Υπάρχει νεότερη έκδοση του Deluge διαθέσιμη. Θέλετε να μεταφερθείτε στη " -"σελίδα λήψης μας;" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Συνδέσεις" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Λαμβάνεται" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Αποστέλεται" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Πελάτης Bittorrent" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Επιλογή ευρετηρίου αποθήκευσης" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Ένα λάθος παρατηρήθηκε κατά την προσθήκη του torrent. Είναι πιθανό το αρχείο " -".torrent να είναι κατεστραμμένο.." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Άγνωστο διπλότυπο λάθος torrent." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Δεν υπάρχει αρκετός ελεύθερος χώρος στο δίσκο για να ολοκληρωθεί το " -"κατέβασμα του αρχείου σας" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Απαιτούμενος Χώρος:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Διαθέσιμος Χώρος:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Προσθήκη torrent από URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Εισάγετε το URL του .torrent που θέλετε να κατεβάσετε" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Προσοχή - όλα τα αρχεία αυτού του torrent που έχουν κατέβει ήδη θα " -"διαγραφούν!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" -"Είστε σίγουροι ότι θέλετε να αφαιρεθούν όλα τα torrents που διαμοιράζουν;" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Σε αναμονή" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Ελέχγεται" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Γίνεται σύνδεση" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Λήψη Μεταδεδομένων" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Γίνεται λήψη" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Ολοκληρώθηκε" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Ανάθεση Χώρου" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes χρειάζονται" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" -"Δεν υπάρχει αρκετός διαθέσιμος χώρος για να ολοκληρώσετε το κατέβασμα." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Στάλθηκε ανακοίνωση" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Ανακοίνωση ΟΚ" - -#: src/core.py:774 -msgid "Alert" -msgstr "Συναγερμός" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "Κωδικός HTTP" - -#: src/core.py:776 -msgid "times in a row" -msgstr "φορές συναπτά" - -#: src/core.py:788 -msgid "Warning" -msgstr "Προειδοποιήση" - -#: src/files.py:77 -msgid "Filename" -msgstr "'Ονομα αρχείου" - -#: src/files.py:82 -msgid "Priority" -msgstr "Προτεραιότητα" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Η προτεραιότητα αρχείων μπορεί να επιλεχθεί μόνον όταν χρησιμοποιείται η " -"πλήρης ανάθεση χώρου δίσκου.\n" -"Παρακαλώ αλλάξτε τις ρυθμίσεις σας ώστε να απενεργοποιηθεί η συμπαγής " -"ανάθεση χώρου και κατόπιν αφαιρέστε και ξαναπροσθέστε αυτό το torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Ενεργοποιήθηκε" - -#: src/dialogs.py:445 -#, fuzzy -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Το πρόγραμμα αυτό είναι ελεύθερο λογισμικό. Επιτρέπεται η αναδιανομή ή/και\n" -"τροποποίησή του υπό τους όρους της Γενικής ‘Αδειας Δημόσιας Χρήσης GNU (GNU " -"General Public \n" -" License), όπως αυτή έχει δημοσιευτεί από το Ίδρυμα Ελεύθερου Λογισμικού " -"(Free Software Foundation)\n" -"-είτε της έκδοσης 2 της ‘Αδειας, είτε (κατ' επιλογήν) οποιασδήποτε\n" -"μεταγενέστερης έκδοσης.Το πρόγραμμα αυτό διανέμεται με την ελπίδα ότι\n" -"θα αποδειχθεί χρήσιμο, παρόλα αυτά ΧΩΡΙΣ ΚΑΜΙΑ ΕΓΓΥΗΣΗ –χωρίς ούτε\n" -"και την σιωπηρή εγγύηση ΕΜΠΟΡΕΥΣΙΜΟΤΗΤΑΣ ή ΚΑΤΑΛΛΗΛΟΤΗΤΑΣ\n" -"ΓΙΑ ΣΥΓΚΕΚΡΙΜΕΝΗ ΧΡΗΣΗ. Για περισσότερες λεπτομέρειες ανατρέξτε\n" -"στη Γενική ‘Αδεια Δημόσιας Χρήσης GNU (GNU General Public License).\n" -"Θα πρέπει να έχετε λάβει ένα αντίγραφο της\n" -"Γενικής ‘Αδειας Δημόσιας Χρήσης GNU (GNU General Public License) μαζί με " -"αυτό το πρόγραμμα.\n" -"Εάν όχι, επικοινωνήστε γραπτώς με το Ίδρυμα Ελεύθερου Λογισμικού (Free " -"Software Foundation),\n" -" Inc., 59 Temple Place, Suite 330, Boston, MA 02111-\n" -"1307 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Επιλογή αρχείου .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Αρχεία torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Όλα τα αρχεία" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Εξωτερική εντολή" - -#: src/common.py:207 -msgid "not found" -msgstr "δεν βρέθηκε" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Κατεβάστε και εισάγετε διάφορες μαύρες λίστες διευθύνσεων ΙΡ\n" -"\n" -"Αυτή τη στιγμή το plugin αυτό μπορεί να διαχειριστή λίστες μορφής\n" -"PeerGuardian (δυαδικής μορφής ή κειμένου), SafePeer και Emule. Το\n" -"μορφότυπο 7zip του PeerGuardian δεν υποστηρίζεται. Τα αρχεία\n" -"μπορούν να δίνονται ως URL ή τοποθεσίες στο τοπικό σύστημα \n" -"αρχείων.\n" -"\n" -"Μία σελίδα με δείκτες σε σελίδες λήψης μαύρων λιστών είναι διαθέσιμη\n" -"στο wikiQ\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "Κείμενο PeerGuardian (Ασυμπίεστο)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Λίστα IP του Emule (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "Κείμενο SafePeer (Συμπιεσμένο)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Αδυναμία λήψης του URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Δεν ήταν δυνατό το άνοιγμα του αρχείου με τη λίστα φραγών" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Λανθασμέμος τύπος αρχείου ή κατεστραμμένο αρχείο λίστας φραγών" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Εισηγμένο" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP διευθύνσεις" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Μαύρη Λίστα" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "καταχωρήσεις" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL Μαύρης Λίστας" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Κατέβασμα νέας λίστας μπλοκαρισμένων διευθύνσεων κάθε" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "μέρες" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Φόρτωση και εγκατάσταση μαύρης λίστας" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Εισαγωγή" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Ολοκληρώθηκε" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Περιμέναμε ένα αρχείου gzip, αλλά δεν λάβαμε τέτοιο, ή πιθανώς το αρχείο " -"είναι κατεστραμμένο. Παρακαλούμε διορθώστε τις επιλογές Blocklist σας." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Μη έγκυρος ηγέτης" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Μη έγκυρος μαγικός κωδικός" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Λάθος έκδοση" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Ορίστε την επιθυμητή αναλογία για ένα torrent" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Επιθυμητή Αναλογία" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Δεν έχει οριστεί" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Δεν έχει τεθεί" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Επιθυμητή αναλογία" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Εδώ φαίνονται οι συνδεδεμένοι υπολογιστές για κάθε torrent καθώς και η ΙΡ " -"διεύθυνση τους, η χώρα, η εφαρμογή, το ποσοστό που έχει ολοκληρωθεί καθώς " -"και οι ταχύτητες λήψης και αποστολής.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Διεύθυνση IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Πελάτης" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Ποσοστό ολοκλήρωσης" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Δημιουργία Torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Αυτό το torrent θα δημιουργηθεί από ένα μοναδικό αρχείο" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Αρχείο:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Αυτό το torrent θα δημιουργηθεί από ένα ευρετήριο" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Φάκελος:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Πηγή" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Αποθήκευση Αρχείου Torrent Ως:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Φόρτωση αυτού του torrent στο Deluge για διαμοιρασμό" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Προσθήκη νέου torrent στην ουρά" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Αρχείο Torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Ιχνηλάτες" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Σχόλια" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Συγγραφέας" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Ορισμός ιδιωτικής σημαίας" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Όσο μικρότερα είναι τα κομάτια, τόσο πιο αποτελεσματικές θα είναι οι " -"μεταφορές, αλλά το αρχείο \".torrent\" θα είναι μεγαλύτερο." - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Μέγεθος Κοματιού:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Προχωρημένες" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Ένα plugin δημιουργίας torrent" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Νέο Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Νέο Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Δημιουργία Νέου Torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Αποθήκευση αρχείου ως..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Πρέπει να επιλέξετε μια πηγή για το torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Πρέπει να επιλέξετε ένα αρχείο όπου θα αποθηκεύσετε το torrent." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Επιλογές Ειδοποιήσεων Torrents" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" -"Ενεργοποίηση ήχου συμβάντων (απαιτεί το pygame, μη διαθέσιμο σε Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Ενεργοποίηση τρεμοπαίγματος εικονιδίου μπάρας συστήματος" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Ενεργοποίηση αναδυόμενης ειδοποίησης (απαιτεί python-notify, μη διαθέσιμο σε " -"Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Ενημέρωση για ολοκλήρωση λήψης torrent μέσω τρεμοπαίγματος του εικονιδίου " -"στην μπάρα συστήματος ή/και αναδυόμενη ειδοποίηση." - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Ολοκλήρωση torrent" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Πρόσθετη λειτουργία για την παρακολούθηση της υγείας (κατάστασης) του " -"δικτύου\n" -"\n" -"Συγγραφέας: Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Υγεία: ΟΚ]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Προτιμήσεις Αναφοράς Συμβάντων" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Ενεργοποίηση αρχείων αναφοράς" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Αρχεία αναφοράς" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Ο απομακρυσμένος υπολογιστής είναι στην μαύρη λίστα." - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Ολοκληρώθηκε το τεμάχιο" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Λήψη τεμαχίου" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Ολοκληρώθηκε το κομμάτι" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Μεταφορά χώρου αποθήκευσης" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Προειδοποίηση ιχνηλάτη" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Συναγερμός ιχνηλάτη" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Απάντηση ιχνηλάτη" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Ανακοίνωση ιχνηλάτη" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Σφάλμα απόρριψης ταχείας συνέχισης" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Σφάλμα απαγόρευσης σύνδεσης" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Σφάλμα αποτυχίας hash" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Σφάλμα στο Αρχείο" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Μη έγκυρο αίτημα" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Μηνύματα συνδεδεμένων υπολογιστών" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Ολοκληρώθηκε το torrent" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Επιλογή συμβάντων προς αναφορά" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Προστίθεται μία καρτέλα με αναφορές από τα επιλεγμένα\n" -"συμβάντα.\n" -"\n" -"Τα μηνύματα συμβάντων προέρχονται από την βιβλιοθήκη \n" -"libtorrent. Εάν επιθυμείτε να μεταφραστούν αυτά τα μηνύματα\n" -"στη γλώσσα σας, θα πρέπει να αναφέρετε το θέμα στη libtorrent\n" -"και όχι το deluge.\n" -"\n" -"Σχετικά με τα αρχεία αναφορών, οι αναφορές αποθηκεύονται \n" -"σε ένα ευρετήριο αναφορών μέσα στο ευρετήριο ρυθμίσεων \n" -"του deluge. Τα μηνύματα συμβάντων διαφορετικών torrents \n" -"διατηρούνται σε διαφορετικά αρχεία αναφορών, με όνομα ίδιο\n" -"με το σχετιζόμενο .torrent. Τα μηνύματα συμβάντων που δεν \n" -"σχετίζονται με κάποιο συγκεκριμένο torrent αποθηκεύονται \n" -"σε αρχεία ονομασμένα σύμφωνα με τα ονόματα των συμβάντων\n" -"(πχ. peer_messages.log).\n" -"Τα μηνύματα συμβάντων μέσα στα αρχεία αναφορών επίσης\n" -"διαθέτουν μία ημερομηνία και ώρα. \n" -"Ο χρήστης είναι υπεύθυνος με τον καθαρισμό των αναφορών.\n" -"\n" -"Από την έκδοση 0.2\n" -"Κατά την εμφάνισή τους τα αρχεία συμβάντων φαίνονται\n" -"τμηματικά, τα αρχεία όμως παραμένουν ατόφια.\n" -"Τα νεότερα συμβάντα εμφανίζονται στην κορυφή.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Αναφορά Συμβάντων" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "μήνυμα συμβάντος: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Μήνυμα συνδεδεμένου υπολογιστή:" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "διεύθυνση δικτύου: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "πελάτης: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "ευρετήριο τμημάτων: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "κωδικός κατάστασης: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Φορές συναπτά: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "ευρετήριο τεμαχίων: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "ταχύτητα σύνδεσης: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Ορίστε το επιθυμητό όριο ταχύτητας ανά torrent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Ταχύτητα _Λήψης Torrent" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Ταχύτητα _Αποστολής Torrent" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Ταχύτητα Αποστολής Torrent (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Ταχύτητα Λήψης Torrent (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Plugin Γραφήματος Δραστηριότητας Δικτύου\n" -"\n" -"Συγγραφέας: Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Γράφημα" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Πρόοδος" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Υπήρξε ένα σφάλμα κατά την εκτέλεση του αρχείου." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Αυτό το plugin εμφανίζει τα αρχεία εντός ενός torrent και επιτρέπει να " -"θέσετε διαφορετικές προτεραιότητες για το καθένα από αυτά, καθώς και να " -"επιλέξετε ποια επιθυμείτε να κατεβάσετε και ποια όχι.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Αρχεία" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Μετακίνηση Torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Επιλογή προορισμού για τη μετακίνηση των αρχείων" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Μετακίνηση των ολοκληρωμένων λήψεων στο:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-άκυρο" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ΟΚ" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Όριο κατεβάσματος:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Όριο ανεβάσματος:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Ενεργά torrents:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Πράσινο για τα άνω όρια, κίτρινο για τα κάτω όρια και κόκκινο για τη διακοπή" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Αν ένα όριο καθορίζεται ως -1, είναι απεριόριστο." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Αριθμός θύρας" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Νέος Κωδικός" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Νέος Κωδικός(επιβεβαίωση)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Πρότυπο" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Πρότυπο κουμπιών" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Πρότυπα λανθάνουσας μνήμης" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Κείμενο και Εικόνα" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Μόνο Εικόνα" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Μόνο κείμενο" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Ισχύων κωδικός <> Νέος κωδικός\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Επιλέξτε είτε url είτε torrent, όχι και τα δύο" - -#: plugins/WebUi/deluge_webserver.py:203 -#, fuzzy -msgid "no data." -msgstr "δεν υπάρχουν δεδομένα." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "η ανανέωση πρέπει να είναι > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Περί" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Προσθήκη torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Εφαρμογή" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Αύτοματη ανανέωση:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Ρύθμιση" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Διαγραφή ληφθέντων αρχείων" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Απενεργοποίηση" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Λήφθηκαν" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Ενεργοποίηση" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Σφάλμα" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Σύνδεση" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Έξοδος" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Νέα ανακοίνωση" - -#: plugins/WebUi/scripts/template_strings.py:29 -#, fuzzy -msgid "Off" -msgstr "Ανενεργό" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Ο κωδικός που εισάγατε είναι μη έγκυρος, προσπαθήστε ξανά" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Παύση όλων" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Κομάτια" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Ανανέωση σελίδας κάθε:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Αφαίρεση torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Επαναφορά όλων" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Ορισμός" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Ορισμός χρονικού περιθωρίου" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Ταχύτητα" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Έναρξη" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Υποβολή" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Λίστα torrent" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Συνολικό μέγεθος" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Ιχνηλάτης" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Κατάσταση ιχνηλάτη" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Αποστολή torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -#, fuzzy -msgid "Uploaded" -msgstr "Απεσταλμένα" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "δευτερόλεπτα" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Η ανάδραση θα επιτευχθεί αυτόματα, βάσει του διαστήματος ενημέρωσης." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Η ανάδραση πρέπει να ανανεώνεται χειροκίνητα." - -#: plugins/FlexRSS/FlexRSS.glade:116 -#, fuzzy -msgid "Disabled" -msgstr "Απενεργοποιημένο" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Διάστημα ενημέρωσης" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Ροές" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Τύπος" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Ροή" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Πληροφορίες" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Υποδείγματα" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Από" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Περίοδος" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Επεισόδιο" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Περιορισμός ιστορικού" - -#: plugins/FlexRSS/FlexRSS.glade:810 -#, fuzzy -msgid "Doesn't Match" -msgstr "Δεν ταιριάζει" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Έτος" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Μήνας" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Ημέρα" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Δοκιμή" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Εισαγωγή torrent στην κορυφή της ουράς." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -#, fuzzy -msgid "Set state to paused." -msgstr "Ορισμός κατάστασης σε παύση." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Λήψη" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Αντικατάσταση" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Μοτίβο" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Επανεγγραφή συνδέσμων" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Το περιεχόμενο θα αποθηκευτεί στον προεπιπιλεγμένο κατάλογο του Deluge, " -"ειδάλλως θα εμφανιστεί μία ειδοποίηση αν δεν έχει οριστεί κατάλογος." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -#, fuzzy -msgid "Deluge default" -msgstr "Προεπιλογές του Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Το περιεχόμενο θα ληφθεί αυτόματα στον καθορισμένο κατάλογο." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Επιλέξτε:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Έξοδος" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Φίλτρα" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Εμφάνιση ενός FlexRSS στη γραμμή εργαλείων του Deluge." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Εμφάνιση κουμπιού στη γραμμή εργαλείων." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Διεπαφή" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Μονοπάτι" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Τιμή" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Ρυθμίσεις" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Διαχείριση πρόσθετων Μηχανών αναζήτησης" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Όνομα:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Προσθέστε μια νέα μηχανή αναζήτησης εισάγοντας ένα Όνομα και μία URL. Για " -"Όνομα, εισάγετε το όνομα της μηχανής αναζήτησης που θα χρησιμοποιηθεί. Για " -"URL, εισάγετε την διεύθυνση url της σελίδας αναζήτησης. Το αλφαριθμητικό που " -"παρέχεται από τον χρήστη θα αντικαθιστά κάθε εμφάνιση μορφής ${query} στην " -"URL.\n" -"Για παράδειγμα μία αναζήτηση μέσω Google θα ήταν:\n" -"Όνομα: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Βοήθεια" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Αλφαριθμητικό Αναζήτησης" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Επιλέξτε Μηχανή" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Διαχείρηση Μηχανών" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Αναζήτηση " diff --git a/po/en_AU.po b/po/en_AU.po deleted file mode 100644 index 0b0fb3bc2..000000000 --- a/po/en_AU.po +++ /dev/null @@ -1,2559 +0,0 @@ -# English (Australia) translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-29 01:53+0000\n" -"Last-Translator: John Garland \n" -"Language-Team: English (Australia) \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Add Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Add" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Remove Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Remove" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Clear Seeding Torrents" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Clear" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Start or Resume Torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Resume" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pause Torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pause" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Queue Torrent Up" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Up" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Queue Torrent Down" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Down" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Change Deluge preferences" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Preferences" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugins" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_File" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Add Torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Add _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Clear Completed" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Edit" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_gins" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_View" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Toolbar" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Details" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Columns" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Size" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Status" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Seeders" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Peers" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Down Speed" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Up Speed" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Time Remaining" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Availability" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Share Ratio" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Help" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Donate to Deluge Development" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Donate" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Homepage" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Community" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Help translate this application" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Translate This Application..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Runs the first-time configuration wizard" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Run Configuration Wizard" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Downloaded:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Uploaded:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Seeders:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Share Ratio:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Speed:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Peers:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "ETA:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Pieces:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Availability:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistics" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# of files:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Total Size:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Tracker Status:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Next Announce:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Name:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Path:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrent Info" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Details" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Delete downloaded files" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Delete .torrent file" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Show/Hide" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Add a Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Clear Finished" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Open File" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Select All" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Unselect All" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Don't download" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "High" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Highest" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge Merge Tracker Lists" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge Preferences" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Ask where to save each download" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Select A Folder" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Store all torrent files in:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Store all downloads in:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Download Location" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Autoload all torrent files in:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Autoload" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maximum simultaneous active torrents:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Enable selecting files for torrents before loading" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Only show if torrent has more than 1 file" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Prioritize first and last pieces of files in torrent" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Start torrents in paused state" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Use Full Allocation" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Compact allocation only allocates space as needed" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Use Compact Allocation" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Allocation" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Downloads" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "From:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "To:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge will automatically choose a different port to use every time." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Random Ports" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Test Active Port" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Active Port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Distributed hash table may improve the amount of active connections." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Enable Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Port Mapping Protocol" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Peer Exchange" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Local Peer Discovery" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Network Extras" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Inbound:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Disabled\n" -"Enabled\n" -"Forced" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Outbound:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Prefer to encrypt the entire stream" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Level:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Handshake\n" -"Full Stream\n" -"Either" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Encryption" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Network" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Queue torrents to bottom when they begin seeding" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Queue new torrents above completed ones" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Stop seeding torrents when their share ratio reaches:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Automatically clear torrents that reach the max share ratio" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Stop seeding torrents when their seed time reaches:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Number of hours" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "Automatically clear torrents that reach the max seed time" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maximum Connection Attempts per Second:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "The maximum upload slots for all torrents. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "The maximum upload speed for all torrents. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "The maximum download speed for all torrents. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maximum Download Speed (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "The maximum number of connections allowed. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maximum Connections:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maximum Upload Speed (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maximum Upload Slots:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maximum Half-Open Connections:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Global Bandwidth Usage" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "The maximum upload slots per torrent. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"The maximum number of connections per torrent. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Per Torrent Bandwidth Usage" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Bandwidth" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Affects regular bittorrent peers" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Password" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Username" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxy type" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxies" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Enable system tray icon" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimize to tray on close" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Start in tray" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Password protect system tray" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Password:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "System Tray" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Use the advanced progress bar (uses slightly more CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Detailed Progress Bar" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Be alerted about new releases" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Updates" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "System Information" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Other" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Force Recheck" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Re_sume" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pause" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Remove Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Tracker Options" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Update Tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Edit Trackers" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Scrape Tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Queue" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Top" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Up" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Down" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Bottom" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Open Containing Folder" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Show Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Resume All" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Pause All" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Download Speed Limit" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Upload Speed Limit" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Quit" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Edit Trackers" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Tracker Editing" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge File Selection" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrent will not be distributed on the trackerless (DHT) network" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Set the private flag" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "First Launch Configuration" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Use _Random Ports" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Ask where to save each file" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Store all downloads in: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maximum Active Torrents:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Your Upload Line Speed:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Unlimited" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Activated" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Other..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Download Speed (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Upload Speed (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge is locked" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infinity" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Unknown" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Name" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Avail." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Ratio" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Choose a directory to switch torrent source to" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Delete the old torrent source?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Paused %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Queued %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Connections" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Download" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Upload" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent Client" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Choose a download directory" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Unknown duplicate torrent error." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "There is not enough free disk space to complete your download." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Space Needed:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Available Space:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Add torrent from URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Enter the URL of the .torrent to download" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Warning - all downloaded files for this torrent will be deleted!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Are you sure that you want to remove all seeding torrents?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Queued" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Checking" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Connecting" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Downloading Metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Downloading" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Finished" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Allocating" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes needed" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "There is not enough free disk space to complete your download." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Announce sent" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Announce OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Alert" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP code" - -#: src/core.py:776 -msgid "times in a row" -msgstr "times in a row" - -#: src/core.py:788 -msgid "Warning" -msgstr "Warning" - -#: src/files.py:77 -msgid "Filename" -msgstr "Filename" - -#: src/files.py:82 -msgid "Priority" -msgstr "Priority" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Enabled" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Choose a .torrent file" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent files" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "All files" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "External command" - -#: src/common.py:207 -msgid "not found" -msgstr "not found" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Text (Uncompressed)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP list (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Text (Zipped)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Couldn't download URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Couldn't open blocklist file" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Wrong file type or corrupted blocklist file." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Imported" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blocklist" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "entries" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Blocklist URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Download new blocklist every" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "days" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Loading and installing blocklist" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importing" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Complete" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Got format exception for zipfile:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Invalid leader" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Invalid magic code" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Invalid version" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Set the desired ratio for a torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Desired Ratio" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Not Set" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Not Set" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Desired Ratio" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP Address" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Client" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Percent Complete" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrent Creator" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "This torrent will be made from a single file" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "File:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "This torrent will be made from a directory" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Folder:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Source" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Save Torrent File As:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Load this torrent into Deluge for seeding" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Add new torrent to queue" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent File" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackers" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Web Seeds" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Comments" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Author" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Set Private Flag" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Piece Size:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Advanced" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "A torrent creator plugin" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_New Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "New Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Create New Torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Save file as..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "You must select a source for the torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "You must select a file to save the torrent as." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Torrent Notification Preferences" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Enable event sound (requires pygame, not available on Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Enable blinking tray icon" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Enable popup notification (requires python-notify, not available on Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent complete" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Health: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Event Logging Preferences" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Enable log files" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Log files" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Peer blocked" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Block finished" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Block downloading" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Piece finished" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Storage moved" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Tracker warning" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Tracker alert" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Tracker reply" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Tracker announce" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Fastresume rejected error" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Peer ban error" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Hash failed error" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "File error" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Invalid request" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Peer messages" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent finished" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Select events to log" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Event Log" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "event message: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Peer message" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip address: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "client: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "piece index: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "status code: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Times in a row: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "block index: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "peer speed: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Set the desired speed limit per torrent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrent _Download Speed" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrent Upload _Speed" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrent Upload Speed (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrent Download Speed (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graph" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progress" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "There was an error trying to launch the file." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Files" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"his plugin allows users to move the torrent to a different directory without " -"having to remove and re-add the torrent. This feature can be found by right-" -"clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Move Torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Switch Torrent Source" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Choose a directory to move files to" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Move completed downloads to:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "This plugin allows users to add web seeds to their torrents" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Add Web Seed" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Add Web Seed" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Download limit:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Upload limit:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Active torrents:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Upload Slots:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Max Connections:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Scheduler Settings" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Green is the high limits, yellow is the low limits and red is stopped" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "If a limit is set to -1, it is unlimited." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUi Config" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Port Number" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "New Password" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "New Password(confirm)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Template" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Button Style" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Cache Templates" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Text and image" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Image Only" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Text Only" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Confirmed Password <> New Password\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "translate something" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Choose a url or a torrent, not both." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "no data." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "refresh must be > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# Of Files" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "About" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Add torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Apply" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Auto refresh:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Ava" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Config" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Data Dump" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Delete downloaded files." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Disable" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Downloaded" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Enable" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Error" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "ETA" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Login" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Logout" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Next Announce" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Off" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Password is invalid,try again" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pause all" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Pieces" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Queue Down" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Queue Position" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Queue Up" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Reannounce" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Refresh page every:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Remove torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Resume all" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Set" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Set Timeout" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Speed" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Start" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Submit" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrent list" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Total Size" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Tracker Status" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Upload torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Uploaded" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "URL" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "seconds" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Feed will be retrieved automatically, based on the update interval." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Feed must be refreshed manually." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Disabled" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Update Interval" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feeds" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Type" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Information" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Patterns" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "From" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Season" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episode" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Through" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "History Restriction" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Doesn't Match" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Year" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Month" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Day" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Insert torrent at top of queue." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Set state to paused." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Delete filter when matched." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Download" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Replacement" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Pattern" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Link Rewriting" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge default" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Content will be automatically downloaded to the specified directory." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Choose:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Output" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filters" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Show a FlexRSS icon in Deluge's toolbar." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Show button on toolbar." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interface" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Threaded (experimental)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Feed Retrieval" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domain" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Path" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Value" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Configuration" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Manage Search Plugins" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Name:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Help" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Search for torrents anonymously" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Search String" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Choose an Engine" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Manage Engines" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Search " diff --git a/po/en_CA.po b/po/en_CA.po deleted file mode 100644 index 8629e90da..000000000 --- a/po/en_CA.po +++ /dev/null @@ -1,2553 +0,0 @@ -# English (Canada) translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2007-12-31 18:18+0000\n" -"Last-Translator: Guillaume Pelletier \n" -"Language-Team: English (Canada) \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Add Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Add" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Remove Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Remove" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Clear Seeding Torrents" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Clear" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Start or Resume Torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Resume" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pause Torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pause" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Queue Torrent Up" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Up" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Queue Torrent Down" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Down" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Change Deluge preferences" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Preferences" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugins" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_File" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Add Torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Add _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Clear Completed" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Edit" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_gins" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_View" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Toolbar" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Details" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Columns" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Size" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Status" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Seeders" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Peers" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Down Speed" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Up Speed" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Time Remaining" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Availability" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Share Ratio" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Help" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Home" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Community" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Help translate this application" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Translate This Application..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Runs the first-time configuration wizard" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Run Configuration Wizard" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Downloaded:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Uploaded:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Seeders:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Share Ratio:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Speed:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Peers:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "ETA:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Pieces:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Availability:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistics" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# of files:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Total Size:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Tracker Status:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Next Announce:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Name:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Path:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrent Info" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Details" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Delete downloaded files" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Delete .torrent file" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Show/Hide" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Add a Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Clear Finished" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Open File" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Select All" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Unselect All" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Don't download" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "High" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Highest" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge Merge Tracker Lists" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge Preferences" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Ask where to save each download" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Select A Folder" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Store all torrent files in:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Store all downloads in:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Download Location" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Autoload all torrent files in:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Autoload" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maximum simultaneous active torrents:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Enable selecting files for torrents before loading" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Only show if torrent has more than 1 file" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Prioritize first and last pieces of files in torrent" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Start torrents in paused state" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Use Full Allocation" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Compact allocation only allocates space as needed" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Use Compact Allocation" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Allocation" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Downloads" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "From:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "To:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge will automatically choose a different port to use every time." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Random Ports" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Test Active Port" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Active Port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Distributed hash table may improve the amount of active connections." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Enable Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Port Mapping Protocol" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Peer Exchange" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Local Peer Discovery" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Network Extras" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Inbound:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Disabled\n" -"Enabled\n" -"Forced" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Outbound:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Prefer to encrypt the entire stream" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Level:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Handshake\n" -"Full Stream\n" -"Either" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Encryption" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Network" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Queue torrents to bottom when they begin seeding" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Queue new torrents above completed ones" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Stop seeding torrents when their share ratio reaches:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Automatically clear torrents that reach the max share ratio" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"The maximum number of connection attempts per second. A high value may crash " -"some cheap routers. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maximum Connection Attempts per Second:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "The maximum upload slots for all torrents. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "The maximum upload speed for all torrents. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "The maximum download speed for all torrents. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maximum Download Speed (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "The maximum number of connections allowed. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maximum Connections:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maximum Upload Speed (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maximum Upload Slots:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maximum Half-Open Connections:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Global Bandwidth Usage" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "The maximum upload slots per torrent. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"The maximum number of connections per torrent. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Per Torrent Bandwidth Usage" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Bandwidth" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Affects regular bittorrent peers" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Password" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Username" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxy type" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxies" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Enable system tray icon" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimize to tray on close" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Start in tray" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Password protect system tray" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Password:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "System Tray" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Use the advanced progress bar (uses slightly more CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Detailed Progress Bar" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Be alerted about new releases" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Updates" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "System Information" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Other" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Force Recheck" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Re_sume" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pause" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Remove Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Tracker Options" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Update Tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Edit Trackers" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Scrape Tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Queue" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Top" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Up" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Down" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Bottom" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Open Containing Folder" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Show Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Resume All" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Pause All" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Download Speed Limit" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Upload Speed Limit" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Quit" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Edit Trackers" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Tracker Editing" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge File Selection" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrent will not be distributed on the trackerless (DHT) network" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Set the private flag" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "First Launch Configuration" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Use _Random Ports" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Ask where to save each file" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Store all downloads in: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Please select the upload speed of your connection, which will then be used " -"to automatically make suggestions for the settings below" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maximum Active Torrents:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8 Kbps\n" -"56 Kbps\n" -"64 Kbps\n" -"96 Kbps\n" -"128 Kbps\n" -"192 Kbps\n" -"256 Kbps\n" -"384 Kbps\n" -"512 Kbps\n" -"640 Kbps\n" -"768 Kbps\n" -"1 Mbps\n" -"2 Mbps\n" -"10 Mbps\n" -"20 Mbps\n" -"40 Mbps\n" -"50 Mbps\n" -"100 Mbps" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Your Upload Line Speed:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Unable to state browser. Please make sure you have python-gnome2-extras " -"installed or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME " -"environment variables to /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Unlimited" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Activated" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Other..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Download Speed (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Upload Speed (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge is locked" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infinity" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Unknown" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Name" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Avail." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Ratio" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Paused %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Queued %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Connections" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Download" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Upload" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent Client" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Choose a download directory" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Unknown duplicate torrent error." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "There is not enough freedisk space to complete your download." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Space Needed:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Available Space:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Add torrent from URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Enter the URL of the .torrent to download" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Warning - all downloaded files for this torrent will be deleted!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Are you sure you want to remove all seeding torrents?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Queued" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Checking" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Connecting" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Downloading Metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Downloading" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Finished" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Allocating" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes needed" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "There is not enough free disk space to complete your download." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Announce sent" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Announce OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Alert" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP code" - -#: src/core.py:776 -msgid "times in a row" -msgstr "times in a row" - -#: src/core.py:788 -msgid "Warning" -msgstr "Warning" - -#: src/files.py:77 -msgid "Filename" -msgstr "Filename" - -#: src/files.py:82 -msgid "Priority" -msgstr "Priority" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Enabled" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Choose a .torrent file" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent files" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "All files" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "External command" - -#: src/common.py:207 -msgid "not found" -msgstr "not found" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Text (Uncompressed)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP list (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Text (Zipped)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Couldn't download URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Couldn't open blocklist file" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Wrong file type or corrupted blocklist file." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Imported" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blocklist" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "entries" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Blocklist URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "days" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Loading and installing blocklist" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importing" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Complete" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Got format exception for zipfile:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Invalid leader" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Invalid magic code" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Invalid version" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Set the desired ratio for a torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Desired Ratio" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Not Set" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Not Set" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Desired Ratio" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"IP, country, client, percent complete and upload and download speeds.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP Address" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Client" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Percent Complete" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrent Creator" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "This torrent will be made from a single file" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "File:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "This torrent will be made from a directory" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Folder:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Source" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Save Torrent File As:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Load this torrent into Deluge for seeding" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Add new torrent to queue" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent File" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackers" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Web Seeds" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Comments" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Author" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Set Private Flag" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Piece Size:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Advanced" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "A torrent creator plugin" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_New Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "New Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Create New Torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Save file as..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "You must select a source for the torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "You must select a file to save the torrent as." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Torrent Notification Preferences" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Enable event sound (requires pygame, not available on Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Enable blinking tray icon" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Enable popup notification (requires python-notify, not available on Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent complete" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Health: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Event Logging Preferences" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Enable log files" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Log files" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Peer blocked" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Block finished" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Block downloading" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Piece finished" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Storage moved" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Tracker warning" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Tracker alert" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Tracker reply" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Tracker announce" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Fastresume rejected error" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Peer ban error" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Hash failed error" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "File error" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Invalid request" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Peer messages" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent finished" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Select events to log" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Event Log" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "event message: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Peer message" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip address: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "client: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "piece index: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "status code: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Times in a row: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "block index: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "peer speed: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Set the desired speed limit per torrent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrent _Download Speed" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrent Upload _Speed" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrent Upload Speed (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrent Download Speed (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graph" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progress" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "There was an error trying to launch the file." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Files" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Move Torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Choose a directory to move files to" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Move completed downloads to:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "This plugin allows users to add web seeds to their torrents" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Add Web Seed" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Add Web Seed" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Scheduler Settings" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Green is the high limits, yellow is the low limits and red is stopped" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "If a limit is set to -1, it is unlimitted." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUI Config" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Port Number" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "New Password" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "New Password (confirm)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Template" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Button Style" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Cache Templates" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Text and image" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Image Only" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Text Only" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Confirmed Password <> New Password\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "Translate something" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Choose an url or a torrent, not both." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "No data." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "Refresh must be > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# Of Files" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "About" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Add torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Apply" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Auto refresh:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Ava" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Config" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Data Dump" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Delete downloaded files." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Disable" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Downloaded" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Enable" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Error" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "ETA" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Login" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Logout" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Next Announce" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Off" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Password is invalid, please try again" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pause all" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Pieces" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Queue Down" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Queue Position" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Queue Up" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Reannounce" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Refresh page every:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Remove torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Resume all" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Set" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Set Timeout" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Speed" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Start" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Submit" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrent list" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Total Size" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Tracker Status" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Upload torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Uploaded" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "URL" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "seconds" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Feed will be retrieved automatically, based on the update interval." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Feed must be refreshed manually." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Disabled" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Update Interval" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feeds" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Type" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Information" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Patterns" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "From" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Season" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episode" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "History Restriction" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Doesn't Match" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Year" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Month" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Day" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Insert torrent at top of queue." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Set state to paused." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Delete filter when matched." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Download" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Replacement" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Pattern" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Link Rewriting" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Content will be saved to Deluge's default directory. A prompt will appear if " -"none is set." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge default" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Content will be automatically downloaded to the specified directory." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Choose:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Output" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filters" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Show a FlexRSS icon in Deluge's toolbar." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Show button on toolbar." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interface" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Threaded (experimental)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Feed Retrieval" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domain" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Path" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Value" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Configuration" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Manage Search Plugins" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Name:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Help" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Search String" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Choose an Engine" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Manage Engines" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Search " diff --git a/po/en_GB.po b/po/en_GB.po deleted file mode 100644 index d05c108fd..000000000 --- a/po/en_GB.po +++ /dev/null @@ -1,2559 +0,0 @@ -# English (United Kingdom) translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-01 11:18+0000\n" -"Last-Translator: Jeff Bailes \n" -"Language-Team: English (United Kingdom) \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Add Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Add" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Remove Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Remove" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Clear Seeding Torrents" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Clear" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Start or Resume Torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Resume" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pause Torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pause" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Queue Torrent Up" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Up" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Queue Torrent Down" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Down" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Change Deluge preferences" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Preferences" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugins" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_File" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Add Torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Add _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Clear Completed" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Edit" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_gins" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_View" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Toolbar" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Details" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Columns" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Size" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Status" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Seeders" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Peers" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Down Speed" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Up Speed" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Time Remaining" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Availability" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Share Ratio" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Help" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Donate to Deluge Development" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Donate" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Homepage" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Community" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Help translate this application" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "Translate This Application" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Runs the first-time configuration wizard" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Run Configuration Wizard" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Downloaded:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Uploaded:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Seeders:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Share Ratio:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Speed:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Peers:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "ETA:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Pieces:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Availability:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistics" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# of files:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Total Size:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Tracker Status:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Next Announce:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Name:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Path:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrent Info" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Details" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Delete downloaded files" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Delete .torrent file" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Show/Hide" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Add a Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Clear Finished" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Open File" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Select All" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Unselect All" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Don't download" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "High" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Highest" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge Merge Tracker Lists" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge Preferences" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Ask where to save each download" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Select A Folder" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Store all torrent files in:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Store all downloads in:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Download Location" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Autoload all torrent files in:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Autoload" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maximum simultaneous active torrents:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Enable selecting files for torrents before loading" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Only show if torrent has more than 1 file" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Prioritize first and last pieces of files in torrent" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Start torrents in paused state" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Use Full Allocation" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Compact allocation only allocates space as needed" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Use Compact Allocation" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Allocation" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Downloads" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "From:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "To:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge will automatically choose a different port to use every time." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Random Ports" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Test Active Port" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Active Port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Distributed hash table may improve the amount of active connections." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Enable Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Port Mapping Protocol" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Peer Exchange" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Local Peer Discovery" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Network Extras" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Inbound:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Disabled\n" -"Enabled\n" -"Forced" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Outbound:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Prefer to encrypt the entire stream" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Level:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Handshake\n" -"Full Stream\n" -"Either" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Encryption" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Network" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Queue torrents to bottom when they begin seeding" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Queue new torrents above completed ones" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Stop seeding torrents when their share ratio reaches:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Automatically clear torrents that reach the max share ratio" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Stop seeding torrents when their seed time reaches:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Number of hours" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "Automatically clear torrents that reach the max seed time" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maximum Connection Attempts per Second:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "The maximum upload slots for all torrents. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "The maximum upload speed for all torrents. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "The maximum download speed for all torrents. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maximum Download Speed (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "The maximum number of connections allowed. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maximum Connections:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maximum Upload Speed (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maximum Upload Slots:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maximum Half-Open Connections:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Global Bandwidth Usage" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "The maximum upload slots per torrent. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"The maximum number of connections per torrent. Set -1 for unlimited." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Per Torrent Bandwidth Usage" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Bandwidth" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Affects regular bittorrent peers" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Password" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Username" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxy type" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxies" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Enable system tray icon" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimise to tray on close" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Start in tray" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Password protect system tray" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Password:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "System Tray" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Use the advanced progress bar (uses slightly more CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Detailed Progress Bar" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Be alerted about new releases" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Updates" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "System Information" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Other" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Force Recheck" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Re_sume" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pause" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Remove Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Tracker Options" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Update Tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Edit Trackers" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Scrape Tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Queue" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Top" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Up" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Down" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Bottom" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Open Containing Folder" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Show Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Resume All" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Pause All" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Download Speed Limit" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Upload Speed Limit" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Quit" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Edit Trackers" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Tracker Editing" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge File Selection" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrent will not be distributed on the trackerless (DHT) network" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Set the private flag" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "First Launch Configuration" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Use _Random Ports" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Ask where to save each file" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Store all downloads in: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maximum Active Torrents:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Your Upload Line Speed:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Unlimited" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Activated" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Other..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Download Speed (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Upload Speed (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge is locked" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infinity" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Unknown" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Name" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Avail." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Ratio" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Choose a directory to switch torrent source to" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Delete the old torrent source?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Paused %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Queued %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Connections" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Download" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Upload" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent Client" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Choose a download directory" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Unknown duplicate torrent error." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "There is not enough free disk space to complete your download." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Space Needed:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Available Space:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Add torrent from URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Enter the URL of the .torrent to download" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Warning - all downloaded files for this torrent will be deleted!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Are you sure that you want to remove all seeding torrents?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Queued" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Checking" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Connecting" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Downloading Metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Downloading" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Finished" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Allocating" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes needed" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "There is not enough free disk space to complete your download." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Announce Sent" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Announce OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Alert" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP code" - -#: src/core.py:776 -msgid "times in a row" -msgstr "times in a row" - -#: src/core.py:788 -msgid "Warning" -msgstr "Warning" - -#: src/files.py:77 -msgid "Filename" -msgstr "Filename" - -#: src/files.py:82 -msgid "Priority" -msgstr "Priority" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Enabled" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the Licence, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Choose a .torrent file" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent files" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "All files" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "External command" - -#: src/common.py:207 -msgid "not found" -msgstr "not found" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Text (Uncompressed)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP list (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Text (Zipped)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Couldn't download URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Couldn't open blocklist file" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Wrong file type or corrupted blocklist file." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Imported" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blocklist" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "entries" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Blocklist URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Download new blocklist every" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "days" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Loading and installing blocklist" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importing" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Complete" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Got format exception for zipfile:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Invalid leader" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Invalid magic code" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Invalid version" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Set the desired ratio for a torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Desired Ratio" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Not Set" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Not Set" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Desired Ratio" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP Address" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Client" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Percent Complete" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrent Creator" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "This torrent will be made from a single file" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "File:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "This torrent will be made from a directory" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Folder:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Source" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Save Torrent File As:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Load this torrent into Deluge for seeding" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Add new torrent to queue" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent File" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackers" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Web Seeds" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Comments" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Author" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Set Private Flag" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Piece Size:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Advanced" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "A torrent creator plugin" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_New Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "New Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Create New Torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Save file as..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "You must select a source for the torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "You must select a file to save the torrent as." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Torrent Notification Preferences" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Enable event sound (requires pygame, not available on Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Enable blinking tray icon" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Enable popup notification (requires python-notify, not available on Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent complete" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Health: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Event Logging Preferences" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Enable log files" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Log files" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Peer blocked" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Block finished" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Block downloading" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Piece finished" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Storage moved" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Tracker warning" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Tracker alert" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Tracker reply" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Tracker announce" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Fastresume rejected error" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Peer ban error" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Hash failed error" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "File error" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Invalid request" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Peer messages" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent finished" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Select events to log" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Event Log" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "event message: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Peer message" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "IP address: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "client: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "piece index: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "status code: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Times in a row: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "block index: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "peer speed: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Set the desired speed limit per torrent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrent _Download Speed" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrent Upload _Speed" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrent Upload Speed (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrent Download Speed (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graph" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progress" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "There was an error trying to launch the file." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Files" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Move Torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Switch Torrent Source" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Choose a directory to move files to" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Move completed downloads to:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "This plugin allows users to add web seeds to their torrents" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Add Web Seed" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Add Web Seed" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Download limit:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Upload limit:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Active torrents:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Upload Slots:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Max Connections:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Scheduler Settings" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Green is the high limits, yellow is the low limits and red is stopped" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "If a limit is set to -1, it is unlimitted." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUi Config" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Port Number" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "New Password" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "New Password(confirm)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Template" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Button Style" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Cache Templates" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Text and image" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Image Only" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Text Only" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Confirmed Password <> New Password\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "translate something" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Choose an URL or a torrent, not both." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "no data." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "refresh must be > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# Of Files" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "About" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Add torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Apply" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Auto refresh:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Ava" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Config" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Data Dump" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Delete downloaded files." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Disable" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Downloaded" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Enable" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Error" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "ETA" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Login" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Logout" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Next Announce" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Off" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Password is invalid,try again" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pause all" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Pieces" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Queue Down" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Queue Position" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Queue Up" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Reannounce" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Refresh page every:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Remove torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Resume all" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Set" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Set Timeout" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Speed" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Start" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Submit" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrent list" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Total Size" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Tracker Status" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Upload torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Uploaded" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "URL" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "seconds" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Feed will be retrieved automatically, based on the update interval." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Feed must be refreshed manually." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Disabled" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Update Interval" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feeds" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Type" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Information" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Patterns" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "From" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Series" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episode" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Through" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "History Restriction" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Doesn't Match" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Year" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Month" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Day" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Insert torrent at top of queue." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Set state to paused." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Delete filter when matched." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Download" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Replacement" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Pattern" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Link Rewriting" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge default" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Content will be automatically downloaded to the specified directory." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Choose:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Output" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filters" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Show a FlexRSS icon in Deluge's toolbar." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Show button on toolbar." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interface" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Threaded (experimental)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Feed Retrieval" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domain" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Path" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Value" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Configuration" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Manage Search Plugins" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Name:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Help" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Search for torrents anonymously" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Search String" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Choose an Engine" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Manage Engines" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Search " diff --git a/po/eo.po b/po/eo.po deleted file mode 100644 index 3b2a09abd..000000000 --- a/po/eo.po +++ /dev/null @@ -1,2400 +0,0 @@ -# Esperanto translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2007-12-27 13:30+0000\n" -"Last-Translator: Sonja \n" -"Language-Team: Esperanto \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Aldoni torenton" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Aldoni" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Forigi torenton" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Forigi" - -#: glade/delugegtk.glade:56 -#, fuzzy -msgid "Clear Seeding Torrents" -msgstr "Viŝi fontsendantajn torentojn" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Viŝi" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Komenci aŭ reaktivigi torenton" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Reaktivigi" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Paŭzigi torenton" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Paŭzigi" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Supren en la atendovico" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Supren" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Malsupren en la atendovico" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Malsupren" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Agordi Diluvon" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Agordoj" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Kromprogramoj" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Dosiero" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Aldoni torenton" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Aldoni _URL-on" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Viŝi finiĝintajn" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Redakti" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Krompro_gramoj" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torento" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Vidi" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Ilobreto" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detaloj" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Kolumnoj" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Grando" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Stato" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Fontoj" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Samtavolanoj" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Elŝutrapido" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Alŝutrapido" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Disponebleco" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Helpo" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Helpu traduki tiun programon" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Elŝutite:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Alŝutite:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Fontoj:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Rapido:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Samtavolanoj:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Restanta tempo:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Pecoj:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Havebleco:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistikoj" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Dosiernombro:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Kunordiga servilo:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Servila stato:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Sekva konekto:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nomo:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Dosierindiko:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torent-informoj" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detaloj" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Ĉu vi vere volas forigi la elektitajn torentojn de " -"Diluvo?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Forviŝi elŝutitajn dosierojn" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Forviŝi .torrent-dosieron" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "(Mal)kaŝi" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Aldoni torenton..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Viŝi finiĝintajn" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "Malfermi d_osieron" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Elekti ĉiujn" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Malelekti ĉiujn" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Ne elŝuti" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normala" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Grava" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Gravega" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Kunigi servilarojn" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "Jam ezistas tiu torento en Diluvo. Ĉu mi kunigu lla servilarojn?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Agordi Diluvon" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Demandi, kien konservi ĉiun elŝuton" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Elektu dosieron" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Konservi ĉiujn .torent-dosierojn en:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Konservi ĉiujn elŝutojn en:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Aŭtomate elŝuti ĉiujn torent-dosierojn en:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Aŭtomate ŝargi" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"La kvanto da aktivaj torentoj, kiun Diluvo ekrulos. Metu -1 por senlima." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maksimumo da samtempe aktivaj torentoj:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Ebligi elektadon de dosieroj por torentoj antaŭ ol ŝargi" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Nur montri se torento havas pli ol 1 dosiero" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Provu elŝuti la unuan kaj lastan pecojn unue" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Ekigu torentojn en paŭzita stato" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torentoj" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Kun plena disponigo ĉiom el la bezonata spaco por torento antaŭokupiĝas " -"dekomence por eviti diskfragmentiĝon" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Uzu plenan spacdisponigon" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Kun kompakta disponigo la diskospaco nur okupiĝas laŭbezone" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Uzu kompaktan spacdisponigon" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Spacokupado" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Elŝutoj" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Bonvolu noti, ke ŝanĝoj al tiuj agordoj nur plenumiĝos post restartigi " -"Diluvon." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "De:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Al:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Diluvo aŭtomate elektos malsaman porton ĉiufoje." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Hazardaj pordoj" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Provi aktivan pordon" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP-protokolo" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktiva pordo:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Konektado de samtavolanoj" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Nivelo:" - -#: glade/preferences_dialog.glade:931 -#, fuzzy -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Kvitanca reĝimo\n" -"Plena datumstrio\n" -"Aŭ aŭ" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Ĉifrado" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Reto" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Malsuprenigi torentojn en la atendovico kiam ili ekfontsendas" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Fontsendas" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/es.po b/po/es.po deleted file mode 100644 index 57e3a4a4c..000000000 --- a/po/es.po +++ /dev/null @@ -1,2584 +0,0 @@ -# Spanish translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-26 15:17+0000\n" -"Last-Translator: LoLo_SaG \n" -"Language-Team: Spanish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Añadir torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Añadir" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Eliminar torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Eliminar" - -#: glade/delugegtk.glade:56 -#, fuzzy -msgid "Clear Seeding Torrents" -msgstr "Limpiar Torrents Compartidos" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Limpiar" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Iniciar o reanudar torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Reanudar" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pausar torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pausar" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Subir en la cola" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Arriba" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Bajar en la cola" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Abajo" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Cambiar las preferencias" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Preferencias" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Complementos" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Archivo" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Añadir torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Añadir _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Eliminar completados" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Editar" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "_Complementos" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Ver" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Barra de herramientas" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detalles" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "Co_lumnas" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Tamaño" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Estado" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Semillas" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Clientes" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Velocidad de descarga" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Velocidad de subida" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Tiempo restante" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Disponibilidad" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Índice de compartición" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Ayuda" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Donar al Desarrollo de Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Donar" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Página de inicio" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Comunidad" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Ayudar a traducir esta aplicación" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Traducir esta aplicación..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Ejecutar el asistente de configuración de primera ejecución" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "Ejecuta_r asistente de configuración" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Descargado:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Subido:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Semillas:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Porcentaje compartido:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Velocidad:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Clientes:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Tiempo restante estimado:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Partes:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Disponibilidad:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Estadísticas" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Número de archivos:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Tamaño total:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Estado del tracker:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Próximo anuncio:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nombre:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Ruta:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Información del torrent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detalles" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"¿Está seguro de que quiere eliminar el/los " -"torrent(s) seleccionados de Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Eliminar los archivos descargados" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Eliminar archivo .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Mostrar/ocultar" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Añadir un torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Eliminar terminados" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Abrir archivo" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Seleccionar todo" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Deseleccionar todo" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "No descargar" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Alta" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "La más alta" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Combinar lista de rastreadores" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent ya incluido en Deluge, ¿desea combinar la lista de rastreadores?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Preferencias de Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Preguntar dónde guardar cada descarga" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Seleccione una carpeta" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Almacenar todos los archivos torrent en:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Guardar todas las descargas en:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Lugar de descarga" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Autocargar todos los archivos torrent de:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Autocargar" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"El número de torrents activos que Deluge manejará. Use -1 si desea " -"ilimitados." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Máximo número de torrents activos a la vez:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Activar selección de ficheros de los torrent antes de descargar" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Mostrar sólo si el torrent tiene más de 1 archivo" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Priorizar primera y última parte de los archivos del torrent" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Iniciar los torrents pausados" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Asignación completa solicita suficiente espacio en disco para guardar los " -"datos y así previene la fragmentación del disco" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Usar asignación completa" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" -"Asignación compacta sólo emplea lugar en el disco a medida que lo necesita" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Usar asignación compacta" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Asignación de espacio" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Descargas" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Nota - Los cambios para estas configuraciones serán aplicados una vez que " -"reinicie Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Desde:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "A:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge escogerá automáticamente un nuevo puerto cada vez." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Puertos aleatorios" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Comprobar puertos activos" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Puerto activo:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Una tabla hash distribuída puede mejorar la cantidad de conexiones activas." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Activar linea principal DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Plug and Play Universal" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "Protocolo de mapeo de puerto NAT" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Intercambio de clientes" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Búsqueda de clientes locales" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Extras de red" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Entrante:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Desactivado\n" -"Activado\n" -"Forzado" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Saliente:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Preferir encriptrar toda la transferencia" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Nivel:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Negociado\n" -"Flujo completo\n" -"Ninguno" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Encriptación" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Red" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" -"Poner al final de la cola los torrents cuando se empiecen a compartir" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Encolar los nuevos torrents encima de los completados" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Detener los torrents cuando su índice de compartición alcance:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Despejar automáticamente los torrents que alcancen el máximo índice de " -"compartición" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" -"Detener torrents compartidos cuando su tiempo de compartición alcance:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Número de horas" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Automáticamente eliminar torrents que han llegado a su tiempo de " -"compartición máximo" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Compartiendo" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Compartiendo" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"El máximo número de intentos de conexión por segundo. Un valor alto puede " -"bloquear algunos routers baratos. Poner -1 para ilimitado." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Máximos intentos de conexión por segundo:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"La cantidad máxima de slots para todos los torrents. Use -1 si desea " -"ilimitada." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Velocidad máxima de subida para todos los torrents. Use -1 si desea " -"ilimitada." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Velocidad máxima de descarga para todos los torrents. Use -1 si desea " -"ilimitada." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Velocidad máxima de descarga (KB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Número máximo de conexiones permitidas. Use -1 si desea ilimitados." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Conexiones máximas:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Velocidad máxima de subida (KB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Máximo número de puestos de subida:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"La máxima cantidad de conexiones half-open. Un valor alto puede bloquear " -"algunos routers baratos. Use -1 si desea ilimitada." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Máximas conexiones half-open:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Uso global del ancho de banda" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"La cantidad máxima de puestos de subida por torrent. Use -1 si desea " -"ilimitados." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"El número máximo de conexiones por torrent. Use -1 si desea ilimitadas." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Uso del ancho de banda por torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Ancho de banda" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Afecta a clientes regulares de bittorrent" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Proxy de cliente" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Puerto" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Servidor" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Ninguno\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 (c/autent.)\n" -"HTTP\n" -"HTTP (c/autent.)" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Contraseña" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Usuario" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Tipo de proxy" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Proxy del cliente" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Proxy de rastreador" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Proxy del tracker" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Proxy de DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Proxy DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Proxy de semillas web" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Proxy de semillas web" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxies" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Activar icono en el área de notificación" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimizar en el área de notificación al cerrar" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Abrir minimizado en el área de notificación" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Proteger con contraseña el área de notificación" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Contraseña:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Área de notificación" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Usar la barra de progreso avanzada (usa ligeramente más CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Barra de progreso detallada" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge revisará nuestros servidores y te dirá si se ha publicado una nueva " -"versión" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Ser notificado de nuevas versiones" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Actualizaciones" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Ayudanos a mejorar Deluge enviandonos tus versiones de Python y PyGTK,\n" -"sistema operativo y tipo de procesador. Ninguna otra información\n" -"es enviada en absoluto." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Información del sistema" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Otro" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Forzar la comprobación" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "_Continuar" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pausa" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "Elimina_r torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "Opciones del ras_treador" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "Act_ualizar el rastreador" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Editar rastreadores" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "Ra_spar rastreador" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Cola" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "Primero(_T)" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "S_ubir" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Bajar" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Inferior" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Abrir carpeta contenedora" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "Mo_strar Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Reanudar todo" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Pausar todo" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Límite de velocidad de descarga" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Límite de velocidad de subida" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Salir" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Editar rastreadores" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Edición de rastreadores" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Selección de ficheros de Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "El torrent no será distribuido en redes (DHT) sin rastreadores" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Marcar como privado" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Configuración de primer inicio" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Este asistente le ayuda a configurar Deluge a su gusto. Si es un nuevo " -"usuario de Deluge, por favor dese cuenta de que la mayoría de " -"funcionalidades y características de Deluge se encuentran en el formulario " -"de complementos, al cual se puede acceder pulsando en Complementos en el " -"menú Editar." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge necesita un rango de puertos donde intenta escuchar las conexiones " -"entrantes. El rango de puertos por defecto de bittorrent son 6881-6889, " -"muchos ISPs bloquean estos puertos por lo que animamos a que seleccione " -"otros, entre 49152 y 65535. Como alternativa, puede dejar que Deluge " -"seleccione los puertos aleatoriamente." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Usar pue_rtos aleatorios" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"¿Desea que Deluge descargue automáticamente a un lugar predefinido o desea " -"especificarlo para cada descarga?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Preguntar donde guardar cada archivo" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Almacenar todas la descargas en: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Por favor seleccione la velocidad de subida de su conexión, será usada para, " -"automáticamente, hacerle sugerencias en las configuraciones siguientes" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Máximos torrents activos:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Velocidad de subida de tu línea:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"A_yudenos a mejorar Deluge enviandonos su versión de Python\n" -"y PyGTK, SO y tipo de procesador. Ninguna otra información\n" -"es enviada." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"No ha sido possible encontrar el navegador. Asegurese de tener el paquete " -"python-gnome2-extras instalado o atribuya a las variables de ambiente " -"LD_LIBRARY_PATH y MOZILLA_FIVE_HOME el valor /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Ilimitada" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Activado" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Otros..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Velocidad de descarga (KB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Velocidad de subida (KB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge está bloqueado" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge está protegido con contraseña.\n" -"Para mostrar la ventana de Deluge, por favor introduzca su contraseña" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infinito" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Desconocido" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nombre" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Tiempo estimado" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Dispon." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Proporción" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Seleccione un directorio a donde mover la fuente del torrent" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Eliminar el código del torren antiguo?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Pausado %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "En cola %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Hay una nueva versión de Deluge. ¿Quieres ir a nuestro sitio de descargas?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Conexiones" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Descargar" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Subir" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge - Cliente Bittorrent" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Elija un directorio de descarga" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Un error ha ocurrido mientras se intentaba añadir el torrent. Es posible que " -"el archivo .torrent esté corrupto." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Error desconocido de duplicación del torrent." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "No hay suficiente espacio en el disco para completar tu descarga." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Espacio necesario:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Espacio disponible:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Añadir torrent desde dirección URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Introduzca la dirección del .torrent para descargar" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Advertencia - ¡todos los archivos descargados de este torrent serán " -"eliminados!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" -"¿Esta seguro que deseas borrar todos los torrents que estas subiendo?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "En cola" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Comprobando" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Conectando" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Descargando metadatos" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Descargando" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Terminado" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Asignando" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes necesarios" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "No hay suficiente espacio libre para terminar la descarga." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Anuncio enviado" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Anuncio correcto" - -#: src/core.py:774 -msgid "Alert" -msgstr "Alerta" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "Código HTTP" - -#: src/core.py:776 -msgid "times in a row" -msgstr "veces en una fila" - -#: src/core.py:788 -msgid "Warning" -msgstr "Precaución" - -#: src/files.py:77 -msgid "Filename" -msgstr "Nombre del archivo" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioridad" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"La prioridad del archivo sólo puede ser fijada cuando se usa la asignación " -"completa.\n" -"Por favor cambie sus preferencias para desactivar la asignación compacta, " -"luego elimine y vuelva a añadir este torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Complemento" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Activado" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge es software libre, puedes distribuirlo y/o\n" -"modificarlo bajo los términos de la GNU General Public\n" -"License publicada por la Free Software Foundation,\n" -"versión 2 de la Licencia, o (a tu elección) cualquier\n" -"versión posterior. Deluge es distribuido con la esperanza\n" -"de que sea útil, pero SIN GARANTÍA, incluso sin la\n" -"tácita de la MERCANTILIDAD o PROPOSITO PARTICULAR.\n" -"Lea la GNU General Public License para mayores detalles.\n" -"Deberías haber recibido una copia de GNU General Public\n" -"License con Deluge, pero si no es así, escribe a Free\n" -"Software Foundation, Inc., 51 Franklin St, Fifth Floor,\n" -"Boston, MA 02110-1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Elija un archivo .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Archivos torrents" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Todos los archivos" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Comando externo" - -#: src/common.py:207 -msgid "not found" -msgstr "no encontrado" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Descarga e importa varias listas de bloqueo de IP.\n" -"\n" -"Actualmente este complemento puede manejar listas de PeerGuardian\n" -"(binario y texto), SafePeer y eMule. El formato 7zip de PeerGuardian\n" -"no está soportado. Los archivos deben ser especificados como URLs o\n" -"rutas en el sistema de archivos local.\n" -"\n" -"Hay en el wiki una página para la descarga de las listas de bloqueo:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "Archivo de texto de PeerGuardian (descomprimido)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Lista IP de Emule (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "Archivo de texto de SafePeer (comprimido en zip)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "No se puede descargar la URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "No se puede abrir el archivo de lista de bloqueo" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Tipo de archivo de lista de bloqueo erróneo o corrupto." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importado" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Lista de bloqueo" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "entradas" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL de la lista de bloqueo" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Descargar una nueva lista de bloqueo cada" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "días" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Cargar e instalar lista de bloqueos" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importando" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Completado" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Se obtuvo una excepción de formato del archivo zip:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Esperábamos un archivo gzip, pero no lo obtuvimos o el archivo está " -"corrupto. Por favor edite las preferencias de su lista de bloqueo." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Líder no válido" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Código mágico inválido" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Versión inválida" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Fijar el ratio deseado para el torrent" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "Ratio _deseado" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_No fijado" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "No fijado" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Ratio deseado" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Muestra los clientes asociados con cada torrente y su ip, país, programa " -"cliente, porcentaje completado y las velocidades de subida y descarga.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Dirección IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Cliente" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Porcentaje completado" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Creador de torrents" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Este torrent será creado a partir de un único archivo." - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Archivo:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Este torrent será creado a partir de un directorio." - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Carpeta:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Origen" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Guardar torrent como:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Cargar este torrent en Deluge para compartir" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Añadir nuevo torrent a la cola" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Archivo torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Rastreadores" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Semillas Web" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Comentarios" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Marcar como privado" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Cuanto más pequeñas sean las partes, más eficiente será la transferencia, " -"pero el archivo \".torrent\" real será más grande" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Tamaño de la parte:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Avanzado" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Un plugin para crear torrents" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Nuevo torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Nuevo torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Crear nuevo torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Guardar archivo como…" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Debe seleccionar una fuente para el torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Debe seleccionar un archivo para grabar el torrent." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Preferencias de notificaciones de torrents" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Activar sonido de suceso (requiere pygame, no disponible en Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Habilitar icono del área de notificación parpadeante" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Activar notificación emergente (requiere python-notify, no disponible en " -"Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Hace que el icono del área de notificación parpadee cuando un torrent " -"finaliza la descarga y/o muestra una notificación emergente" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent completo" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Plugin Monitor de estado de la red\n" -"\n" -"Escrito por Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Estado: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Preferencias de registro de eventos" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Habilitar archivos de registro" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Archivos de registro" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Par bloqueado" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Bloque finalizado" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Bloque descargando" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Porción acabada" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Almacenamiento movido" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Advertencia del rastreador" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Alerta del rastreador" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Respuesta del rastreador" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Anuncio del rastreador" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Error de reanudación rápida rechazada" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Error de par prohibido" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Error por fallo en hash" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Error de archivo" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Solicitud no válida" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Mensajes de pares" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent finalizado" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Seleccionar eventos a registrar" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Añade una pestaña con el registro de los eventos seleccionados.\n" -"\n" -"Los mensajes de eventos provienen de alertas de libtorrent.\n" -"Si quieres traducir esos eventos a tu idioma,\n" -"tendrás que reportar el problema a libtorrent, no a deluge.\n" -"\n" -"Con respecto a los archivos de registros, los registros se guardan en\n" -"un directorio de registros dentro del directorio de configuración de\n" -"deluge. Los mensajes de eventos de torrents específicos se guardan\n" -"en archivos de registro individuales con el mismo nombre que el archivo\n" -".torrent asociado. Los mensajes de eventos que no son específicos a\n" -"ningún torrent se guardan en registros con el nombre de los eventos\n" -"(por ejemplo, peer_messages.log).\n" -"Los mensajes de eventos en los archivos de registros incluyen además\n" -"una marca de tiempo.\n" -"El usuario es el responsable de limpiar los registros.\n" -"\n" -"Sobre v0.2\n" -"Los eventos ahora son truncados al ser mostrados. Los archivos de registro " -"no.\n" -"Los nuevos eventos ahora se muestran al principio.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Registro de eventos" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "mensaje de evento: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Mensaje del cliente" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "dirección ip: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "cliente: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "índice de partes: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "código de estado: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Veces seguidas: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "índice de bloques: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "velocidad del par " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Establece el límite de velocidad deseada por torrent" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Velocidad de _descarga del torrent" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "_Velocidad de subida del torrent" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Velocidad de subida del torrent (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Velocidad de descarga del torrent (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Plugin Gráfico de actividad de la red\n" -"\n" -"Escrito por Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Gráfica" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "En proceso" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Hubo un error al intentar ejecutar el archivo." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Este complemento muestra los archivos dentro de un torrent, permite " -"establecer su prioridad y elegir cuáles quieres descargar y cuáles no.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Archivos" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Este complemtento permite a los usuarios mover un torrent a un directorio " -"distinto sin la necesitdad de volver a a añadirlo. Esta característica puede " -"ser encontrada haciendo click derecho sobre un torrent..\n" -"Además, permite al usuario mover torrents terminados a un directorio " -"distinto automáticamente.\n" -"Nota: Los archivos solo pueden ser movidos dentro de la misma partición." - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Mover torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Cambiar fuente del Torrent" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Elige un directorio al que mover los archivos" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"No puedes mover el torrent a una partición diferente. Por favor comprueba " -"tus preferencias. Además, no puedes mover los archivos del torrent al mismo " -"directorio donde ya están almacenados ni moverlos antes de que hayan sido " -"creados." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Mover las descargas finalizadas a:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Este complemento permite a los usuarios añadir semillas web a sus torrents" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Añadir semilla web" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Añadir semilla web" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Límite de descarga:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Límite de subida:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Torrents activos:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Puestos de Subida:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Máximas Conexiones:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Opciones del planificador" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Verdes los límites máximos, amarillos los mínimos y rojo si está parado." - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Si un límite se establece en -1, es ilimitado." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Configurar WebUI" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Número de puerto" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nueva contraseña" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Nueva contraseña(confirmar)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Plantilla" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Aspecto del botón" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Cachear las plantillas" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Texto e imagen" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Sólo imagen" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Sólo texto" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Contraseña confirmada <> Nueva Contraseña\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "traducir algo" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Elige una url o un torrent, pero no los dos" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "sin datos" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "el refresco debe ser > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# de archivos" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Acerca de" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Añadir torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Aplicar" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Auto refrescar:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Disp" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Configurar" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Depurar:Volcado de datos" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Borrar ficheros descargados" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Desactivado" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Descargado" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Activado" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Error" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "T.Est." - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Inicio de sesión" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Cerrar sesión" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Siguiente anuncio" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Desactivado" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Contraseña no válida, inténtalo otra vez" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pausar todo" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Partes" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Bajar cola" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Posición en la cola" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Subir cola" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Reanunciar" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Actualizar pág. cada:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Eliminar torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Reanudar todo" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Definir" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Establecer tiempo de espera" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Velocidad" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Iniciar" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Enviar" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Lista de torrent" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Tamaño total" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Rastreador" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Estado del rastreador" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Subir torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Subido" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "segundos" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"La alimentación puede ser recuperada automáticamente, basado en un intervalo " -"de actualización." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "La alimentación será actualizada manualmente." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Inhabilitado" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Intervalo de actualización" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Fuentes" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tipo" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Fuente" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Información" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Patrón" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "De" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Temporada" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episodio" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "A través de" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Limitar la historia" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "No coincide" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Año" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Mes" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Día" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Prueba" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Insertar el torrent al principio de la cola." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Establecer estado a pausado." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Borrar el filtro cuando coincida." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Descargar" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Reemplazo" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Patrón" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Reescritura del enlace" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"El contenido será guardado al directorio predeterminado de Deluge, o un " -"mensaje aparecerá si ninguno está configurado." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Predeterminado de Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" -"El contenido será automáticamente descargado al directorio especificado." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Elige:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Salida" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtros" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Mostrar el icono de FlexRSS en la barra de herramientas de Deluge." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Mostrar botón en la barra de herramientas." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interfaz" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Las fuentes pueden ser recuperadas y analizadas en sus propios hilos. La " -"aplicación no será bloqueada, pero puede ser poco fiable." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Multitarea (experimental)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Recuperar fuente" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Dominio" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Ruta" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Valor" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Configuración" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Administrar plugins de búsqueda" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nombre:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Añade un nuevo motor de búsqueda introduciendo un Nombre y una URL. Como " -"Nombre, introduce el nombre del motor de búsqueda a usar. Como URL, " -"introduce la url de la página de búsqueda. La búsqueda del usuario " -"reemplazará la instancia &{query} de la URL.\n" -"Por ejemplo, la búsqueda en Google sería:\n" -"Nombre: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Ayuda" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Búsqueda por torrents anónimamente" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Cadena de búsqueda" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Escoge un motor" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Gestionar motores" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Búsqueda " diff --git a/po/et.po b/po/et.po deleted file mode 100644 index cd4cd3bee..000000000 --- a/po/et.po +++ /dev/null @@ -1,2484 +0,0 @@ -# Estonian translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-16 13:32+0000\n" -"Last-Translator: boss01 \n" -"Language-Team: Estonian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Lisa torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Lisa" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Eemalda torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Eemalda" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Puhasta jagavad torrentid" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Eemalda" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Alusta või jätka torrentit" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Jätka" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Peata torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Peata" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Järjekorrasta torrent üles" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Üles" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Järjekorrasta torrent alla" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Alla" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Muuda Deluge seadeid" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Seadistused" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Pluginad" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Fail" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Lisa torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Lisa _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Eemalda lõpetatud" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Redigeerimine" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_ginad" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Vaade" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Tööriistariba" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detailid" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Veerud" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Suurus" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Staatus" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Levitajad" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Masinad" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Alla kiirus" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Üles kiirus" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Aega jäänud" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Kättesaadavus" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Jagamissuhe" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Abi" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Anneta Deluge arendusse" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Anneta" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "Kodu_leht" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_KKK" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "Ko_mmuun" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Aita tõlkida seda programmi" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Tõlgi seda programmi" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Käivitab esmase konfiguratsiooni abimehe" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Käivita konfiguratsiooni abimees" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Allalaetud:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Üleslaetud:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Jagajad:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Jagamise Suhe:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Kiirus:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Kasutajad:" - -# Arvatav Saabumise Aeg -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "ETA:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Tükid:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Saadavus:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistika" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# faili:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Kogusuurus:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Jälitaja:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Jälitaja staatus:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Järgmine Teadeanne:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nimi:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Asukoht:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrenti info" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detailid" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Oled sa kindet, et sa tahad eemaldada valitud " -"torrenti(d) Deluge-st?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Kustuta allalaetud failid" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Kustuta .torrent fail" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Näita/Peida" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Lisa torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Puhastu Lõpetanutest" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Ava fail" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Vali kõik" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Eemalda valik kõigilt" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Ära lae alla" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normaalne" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Kõrge" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Kõrgeim" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge ühenda jälitajate nimekiri" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent juba tuvastatud Deluge poolt. Kas soovid jälitajate nimekirjad " -"ühendada?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge seadistused" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Küsi kuhu salvestada iga allatõmbamine" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Vali kaust" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Salvesta kõik torrenti failid:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Salvesta kõik allalaadimised:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Allalaadimise koht" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Lae automaatselt torrentid:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Automaatlaadimine" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Aktiivsete torrentite arv, mida Deluge kasutab. Määra -1 piiramatu puhul." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maksimaalsene samaaegselt aktiivsed olevad torrentid:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Luba failide valik torrenti jaoks enne laadimist" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Näita juhul, kui torrentis on rohkem kui 1 fail" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Prioritiseeri torrenti esimeste ja viimaste failide tükid" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Alusta torrentid peatatuna" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrentid" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Kasuta täielikku jaotamist" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Kompaktne jaotamine jaotab ainult vajamineva ruumi" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Kasuta kompaktset jaotust" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Jaotus" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Allalaadimised" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Pane Tähele - Nende seadete muudatused rakendatakse peale Deluge " -"taaskäivitamist." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Alates:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Kuni:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge valib igakord automaatselt erineva pordi, mida kasutada." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Juhuslikud pordid" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Testi aktiivset porti" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktiivne port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Hajusräsitabel võib parandada aktiivsete ühenduste arvu." - -#: glade/preferences_dialog.glade:703 -#, fuzzy -msgid "Enable Mainline DHT" -msgstr "Luba põhiriba DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universaalne isehäälestumine" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT pordi vastendus protokoll" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Lähtemasina vahetus" - -#: glade/preferences_dialog.glade:799 -#, fuzzy -msgid "Local Peer Discovery" -msgstr "Otsi kohalike kliente" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Võrgu lisad" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Sisenev:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Keelatud\n" -"Lubatud\n" -"Sunnitud" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Väljuv:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Eelista krüpteerida kogu voog" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Tase:" - -#: glade/preferences_dialog.glade:931 -#, fuzzy -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Käepigistus\n" -"Täis vool\n" -"Mitte kumbgi" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Krüptimine" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Võrk" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Järjekorrasta torrentid alumisteks, kui nad hakkavad levitama" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Järjekorrasta uue torrentid valmisolevatest ülespoole" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Lõpeta torrentite levitamine, kui nende jagamise suhe ulatud:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Eemalda automaatselt torrentid, mis jõuavad maksimaalse jagamissuhteni" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Lõpeta jagamine kui jagamis aeg ületab:" - -#: glade/preferences_dialog.glade:1120 -#, fuzzy -msgid "Number of hours" -msgstr "Tunnid" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "Automaagiliselt eemalda torrentid mis ületavad maksimum jagamis aja" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Üleslaadimised" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Levitamine" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Maksimaalne ühendamise katsete arv sekundis. Suur väärtus võib krahhida " -"mõningaid odavamaid ruutereid. Määra -1 piiramatu puhul." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maksimaalne ühenduste arv sekundis:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Maksimaalselt üleslaadimise pesi kõigile torrentitele. Määra -1 piiramatu " -"puhul." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maksimaalne üleslaadimiskiirus kõigile torrentitele. Määra -1 piiramatu " -"puhul." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maksimaalne allalaadimiskiirus kõigile torrentitele. Määra -1 piiramatu " -"puhul." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maksimaalne allalaadimis kiirus (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Maksimaalselt lubatud ühenduste arv. Määra -1 piiramatu puhul." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maksimaalselt ühendusi:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maksimaalne üleslaadimise kiirus (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maksimaalne üleslaadimiste pesad:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Maksimaalne pool-avatud ühenduste arv. Suurt väärtus võib krahhida mõningaid " -"odavamaid ruutereid. Määra -1 piiramatu puhul." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maksimaalselt pool-avatud ühendusi:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Üldine ülkandekiiruse kasutus" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Maksimaalselt üleslaadimiste pesi igale torrenti kohta. PiiramMäära -1 " -"piiramatu puhul." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Maksimaalne ühenduste arv iga torrenti kohta. Määra -1 piiramatu puhul." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "ülekandekiiruse kasutus iga torrenti kohta" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Ülekandekiirus" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Mõjutab tavalise bittorrenti partnereid" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Partneri proksi" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Pole\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Parool" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Kasutajanimi" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proksi tüüp" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Partneri proksi" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Jälitaja proksi" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Jälitaja proksi" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT proksi" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT proksi" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Veebi partneri proksi" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Veebi partneri proksi" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proksid" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Luba süsteemse salve ikoon" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimeeri salve sulgemisel" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Alusta salves" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Parooliga kaitstud süsteemisalv" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Parool:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Süsteemisalv" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Kasuta arenenud edenemise riba (kasutab pisut rohkem CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Detailne edenemise riba" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge kontrollib meie servereid ja ütled sulle kui uuem versioon on lastud " -"välja" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Ole teavitatud uutest väljalasetet" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Uuendused" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Aita meil täiustada Deluge klienti ja saada oma Pythoni ja PyGTK\n" -"versioonid, OS ja protsessori tüübid. Absoluutselt muud\n" -"andmeid ei edastata." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Süsteemi Informatsioon" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Muu" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Kontrolli uuesti" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Jä_tka" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Peata" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Eemalda torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Jälitaja valikud" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Uuenda jälitajat" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Muuda jälitajaid" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Järjekord" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Ülemine" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Üles" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Alla" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Alumine" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Ava sisaldav kaust" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Näita Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Jätka kõiki" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Peata kõik" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Allalaadimise kiirusepiirang" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Üleslaadimise kiirusepiirang" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Sulge" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Muuda Jälitajaid" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Jälitajate Muutmine" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge failide valik" - -#: glade/files_dialog.glade:42 -#, fuzzy -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrentit ei jagata trackerita võrgus (DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Aseta privaatne lipp" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Esmakäivituse Seaded" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Kasuta _vahelduvaid porte" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Kas Sa soovid, et Deluge tõmbaks automaatselt eelnevalt määratud kohta või " -"soovid iga kord määrata erineva asukoha?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Küsi kuhu iga fail salvestada" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Salvesta kõik allalaadimised: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Palun vali enda ühenduse üleslaadimiskiirus ja programm määrab automaatselt " -"soovitatavad seaded" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maksimaalselt aktiivseid torrenteid:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Sinu ühenduse üleslaadimiskiirus:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Aita meil täiustada programmi ja luba saata anonüümselt Sinu Pythoni, PyGTK " -"versioone ning infot operatsioonisüsteemi ja protsessori kohta. Muud " -"informatsiooni ei koguta." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Piiramatu" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktiveeritud" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Muu..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Allalaadimiste Kiirus (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Üleslaadimiste Kiirus (Kib/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge on lukus" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge on parooliga kaitstud.\n" -"Et näha Deluge akent, palun sisestage oma parool" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Lõpmatu" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Tundmatu" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nimi" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "EETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Saadavus" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Suhe" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Peatatud %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "Deluge on uuendatud. Kas soovid avada allalaadimiste lehe?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Ühendusi" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Kiirus Alla" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Kiirus Üles" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent Klient" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Vali allalaadimise kataloog" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Esines viga, siis kui püüti lisada torrent. On võimalik, et teie .torrent " -"fail on vigane." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Tundmatu torrenti koopia viga." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Allalaadimise lõpetamiseks puudub vajalik kettamaht." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Vajaolev Ruum:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Saadaolev Ruum:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Lisa torrenti URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Sisesta allalaetava .torrent URL" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Hoiatus - kõik allalaetud faild selle torrenti jaoks kustutatakse!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Kindlasti eemaldada kõik jagavad torrentid?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Järjekorras" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Kontrollib" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Ühendamine" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Metaandmete Allalaadimine" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Laeb alla" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Lõpetatud" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Määran asukohta" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "baiti vaja" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Kettal pole piisavalt ruumi, et lõpetada allalaadimine." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Teadaanne saadetud" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Teadaanne korras" - -#: src/core.py:774 -msgid "Alert" -msgstr "Häire" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP kood" - -#: src/core.py:776 -#, fuzzy -msgid "times in a row" -msgstr "korda reas" - -#: src/core.py:788 -msgid "Warning" -msgstr "Hoiatus" - -#: src/files.py:77 -msgid "Filename" -msgstr "Failinimi" - -#: src/files.py:82 -msgid "Priority" -msgstr "Tähtus" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Lubatud" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Vali .torrent fail" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent failid" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Kõik failid" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Väline käsk" - -#: src/common.py:207 -msgid "not found" -msgstr "ei leitud" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Tekst (Kokkupakkimata)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP nimekiri (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Tekst (Zip)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "URL-i ei õnnestu avada" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Musta nimekirja ei õnnestu avada" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Vale faili tüüp või rikutud blokklisti fail." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Imporditud" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP-d" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blokknimekiri" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "sisestused" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Blokklisti Aadress" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "päeva" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Blokklisti laadimine ja installimine" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importimine" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Valmis" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Kehtetu võlukood" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Versiooni viga" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Määra soovitud suhe torrentile." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Soovitud suhe" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Määramata" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Määramata" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Soovitud suhe" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Näitab iga torrenti ühendusi ja nende IP-d, päritolu maad, klienti, tõmmatud " -"protsenti ning alla- ja üleslaadimiste kiirusi.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP Aadress" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klient" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Protsenti Lõpetatud" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrenti looja" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Torrent tehakse ühest failist" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Fail:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Torrent tehakse ühest kaustast" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Kaust:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Allikas" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Salvesta Torrenti Fail Kui:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Lae torrent Deluge-sse seedimiseks" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Lisa järjekorda uus torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrenti Fail" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Jälitajad" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Kommentaarid" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Aseta privaatne lipp" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Mida väiksemad tükid, seda tootlikumad ülekanded on, aga tegelik " -"\".torrent\" fail tuleb suurem" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Tüki suurus:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Täpsemalt" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Lisa torrenti loomiseks" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Uus Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Uus Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Loo Uus Torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Salvesta fail kui..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Torrenti allika valimine on kohustuslik." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Vali failinimi millena torrent salvestada." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Torrenti teavituse eelistused" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Luba sündmuste helid (vajab pygame, Win32 pole saadaval)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Luba vilkuv süsteemse salve ikoon" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "Luba popup teavitamine (vajab python-notify, Win32 pole saadaval)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Allalaadimise lõppedes vilguta süsteemse salve ikooni ja/või näita popup " -"teavitust" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent valmis" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Võrgu Tervise Monitor\n" -"Kirjutanud Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Tervis: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Sündmuste Logimise Eelistused" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Luba logimine" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Logi failid" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Ühendus blokeeritud" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blokk lõpetatud" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Bloki allalaadimine" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "TÜkk lõpetatud" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Ladustus liigutatud" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Jälitaja hoiatus" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Jälitaja hoiatus" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Jälitaja vastus" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Jälitaja teadaanne" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Faili viga" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Vigane päring" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent lõpetatud" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Vali sündmused, mida logida" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Sündmuste logi" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "sündmuse teade: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Masina sõnum" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip aadress: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "klient: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "tüki indeks: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "seisundi kood: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Kordi reas: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "bloki indeks: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Määra kiiruse piirang igale torrentile." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrenti _Tõmbamiskiirus" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrenti _Üleslaadimiskiirus" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrenti Üleslaadimiskiirus (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrenti Allalaadimiskiirus (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Võrguliikluse Graafiku lisa\n" -"Kirjutas Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graafik" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progress" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Faili käivitamisel tekkis tõrge." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Näitab torrentis olevaid faile, võimaldab seada neile erinevaid tõmbamise " -"prioriteete ning valida millised faile tõmmata ja milliseid mitte.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Failid" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Liiguta Torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Vali kaust, kuhu failid liigutada" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Liiguta lõpetatud allalaadimised:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "keela" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Ajakava seaded" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Roheline on kõrgem limiit, kollane madalaim limiit ning punane peatatud" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Kui limiit on -1, siis on see piiramatu." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUi seaded" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Port" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Uus parool" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Uus parool (uuesti)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Mall" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Nupu stiil" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Puhvri mall" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Tekst ja pilt" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Ainult pilt" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Ainult tekst" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "tõlgi midagi" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Vali url või torrent, mitte mõlemat." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "andmed puuduvad." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "uuendus peab olema > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "Failide arv" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Programmist" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Lisa torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Rakenda" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Uuenda automaatselt:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Seadistus" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Kustuta alla laetud failid." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Keela" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Alla laetud" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Luba" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Viga" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Logi sisse" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Lahku" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Järgmine Teatamine" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Väljas" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Vale parool, proovi uuesti" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Peata kõik" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Tükke" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Liiguta alla" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Järjekorra positsioon" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Liiguta üles" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Teadusta uuesti" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Uuenda lehte iga:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Eemalda torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Jätka kõiki" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Sea" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Kiirus" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Alusta" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Sisesta" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrenti nimekiri" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Suurus Kokku" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Jälitaja" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Jälitaja Staatus" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Üles laetud" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekundit" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Väljas" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Uuendamise intervall" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "Veebiaadress" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Kanalid" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tüüp" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Kanal" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Teave" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Mustrid" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Kasutajalt" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Hooaeg" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episood" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Läbi" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Vaste puudub" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Aasta" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Kuu" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Päev" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Lisa torrent järjekorra tippu" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Pane peatatud staatusesse," - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Kustuta filter, kui vaste leitud." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Allalaadimine" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Asendus" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Muster" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge vaikimisi" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Sisu laetakse automaatselt määratud kausta." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Vali:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Väljund" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtrid" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Näita FlexRSS ikooni Deluge tööriistaribal." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Näita nuppu tööriistaribal" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Liides" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domeen" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Asukoht" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Väärtus" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Küpsised" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Seadistus" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Seadista Otsingu Pluginaid" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nimi:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Abi" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Otsingu Märksõna" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Vali Otsingumootor" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Halda Otsingumuutoreid" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Otsi " diff --git a/po/eu.po b/po/eu.po deleted file mode 100644 index 525f043f9..000000000 --- a/po/eu.po +++ /dev/null @@ -1,2390 +0,0 @@ -# Basque translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2006-11-01 15:00+0000\n" -"Last-Translator: Xabi Ezpeleta \n" -"Language-Team: Basque \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Gehitu Torrent-a" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Ezabatu Torrent-a" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "" - -#: glade/delugegtk.glade:106 -#, fuzzy -msgid "Queue Torrent Up" -msgstr "Igo Torrenta Ilaran" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -#, fuzzy -msgid "Queue Torrent Down" -msgstr "Jetsi Torrenta Ilaran" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Fitxategia" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Editatu" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Tamaina" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Haziak" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Bezeroak" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Elkarbanatze Indizea" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Laguntza" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Garbitu bukatutakoak" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge-ko Hobespenak" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Nondik:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Nora:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Elkarbanatzen" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Eguneratu Tracker-a" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Ezezaguna" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Izena" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Konexioak" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Jetsiera" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Igoera" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent Bezeroa" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Ilaran" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Frogatzen" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Deskargatzen" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Amaituta" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Esleitzen" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Fitxategi guztiak" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "egun" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Bezeroa" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Fitxategi akatsa" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Eskaera baliogabea" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Hurrengo Albistea" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Zatiak" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Erabateko Tamaina" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Tracker-aren Egoera" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "segundu" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Kudeatu Bilaketa Plugin-ak" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Izena:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Laguntza" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/fa.po b/po/fa.po deleted file mode 100644 index 77afb742a..000000000 --- a/po/fa.po +++ /dev/null @@ -1,2412 +0,0 @@ -# Persian translation for deluge -# Copyright (c) 2008 Rosetta Contributors and Canonical Ltd 2008 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2008. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-03-20 20:05+0000\n" -"Last-Translator: Artin \n" -"Language-Team: Persian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "افزودن یک تورنت" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "افزودن" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "حذف تورنت" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "حذف" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "حذف تورنتهای کامل شده" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "پاک کردن" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "شروع یا ادامه دریافت تورنت" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "ادامه" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "مکث کردن تورنت" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "مکث" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "بالا بردن تورنت در صف" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "بالا" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "پایین بردن تورنت در صف" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "پایین" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "تغییر تنظیمات دلوگ" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "تنظیمات‌" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "افزونه‌ها" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "پرونده" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "افزودن تورنت" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "افزودن لینک" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "حذف تورنت های کامل شده" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "ویرایش" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "افزونه ها" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "تورنت" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "نما" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_نوار ابزار" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "جزئیات" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "ستون" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "اندازه‌" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "وضعیت‌‌" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "جفتها" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "سرعت پایین" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "سرعت بالا" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "زمان باقی مانده" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "دسترس‌پذیری" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "ضریب اشتراک گذاری" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "راهنما" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "صفحه وب دلوگ" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "سوالات متداول" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "کمک برای ترجمه این نرم افزار" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "ترجمه این نرم افزار" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "اجرای سیستم اتوماتیک تنظیمات اولیه" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "اجرای سیستم اتوماتیک تنظیمات" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "سرعت:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "سایز کامل: " - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "نام:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr ":مسیر" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "جزئیات‌" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "آشکار/مخفی" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "ـباز کردن پرونده" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "گزینش همه" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "لغو انتخاب همه" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "عادی‌" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "زیاد‌" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "بالاترین" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "یک پوشه انتخاب کنید" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "بارگیری‌ها" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "از:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "به:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "درگاه فعال:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "سطح:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "شبکه" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "پهنای باند" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "درگاه‌" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "کارگزار" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"هیچ کدام\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "کلمه عبور" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "نام کاربری" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "رمز عبور:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "غیره" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_مکث" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_بالا" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_بالا" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_پایین" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_پایین" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_خروج" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8کیلوبیت\n" -"56کیلوبیت\n" -"64کیلوبیت\n" -"96کیلوبایت\n" -"128کیلوبایت\n" -"192کیلوبایت\n" -"256کیلوبایت\n" -"384کیلوبایت\n" -"512کیلوبایت\n" -"640کیلوبایت\n" -"768کیلوبایت\n" -"1مگابیت\n" -"2مگابیت\n" -"10مگابیت\n" -"20مگابیت\n" -"40مگابیت\n" -"50مگابیت\n" -"100مگابیت" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "نامحدود" - -#: src/interface.py:325 -msgid "Activated" -msgstr "فعال شده" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "غیره..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "بی‌نهایت" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "ناشناخته" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "نام" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "نسبت" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "اتصال‌ها" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "بارگیری" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "بارگذاری" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "صف‌شده" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "در حال چک کردن" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "در حال اتصال‌" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "در حال بارگیری" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "تمام شده‌" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "هشدار" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "اخطار" - -#: src/files.py:77 -msgid "Filename" -msgstr "نام پرونده" - -#: src/files.py:82 -msgid "Priority" -msgstr "اولویت" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "فعال" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "پرونده‌های Torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "همه‌ی پرونده‌ها" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "دستور خارجی" - -#: src/common.py:207 -msgid "not found" -msgstr "پیدا نشد" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "واردشده" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP ها" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "در حال وارد کردن" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "کامل" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "تکمیل درصد" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "سازنده Torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "پرونده:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "پوشه:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "منبع" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "پیش رفته" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "ـتورنت جدید" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "تورنت جدید" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "ذخیرۀ پرونده به عنوان..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "شما باید یک منبع برای تورنت انتخاب کنید" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "خطا در پرونده" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "ثبت رویداد" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "پیشرفت" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "پرونده‌ها" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "نشانی اینترنتی:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "کلمه عبور جدید" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "کلمه عبور جدید (تکرار)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "قالب" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "متن و عکس" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "فقط عکس" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "فقط متن" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "درباره" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "اضافه کردن تورنت" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "اِعمال" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "پیکربندی" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "غیرفعال کردن‌" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "بارگیری‌شده" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "فعال‌سازی" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "خطا" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "ورود" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "خروج" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "اعلامیه بعدی" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "خاموش" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "کلمه عبور اشتباه می باشد, مجددا سعی کنید" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "مکث کردن همه" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "تکه‌ها" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "تنظیم" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "سرعت‌" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "شروع" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "ارسال" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "فهرست تورنت" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "اندازۀ کل" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "ردیاب" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "وضعیت ردیاب" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "بارگزاری تورنت" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "بارگذاری‌شده" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "نشانی وب" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "ثانیه" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "از کار افتاده" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "نشانی اینترنتی" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "خوراکها" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "نوع‌" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "خوراک" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "اطلاعات" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "بواسطه" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "سال" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "ماه‌" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "روز" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "آزمایش" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "جایگزینی" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "الگو" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "خروجی" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "صافی‌ها" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "واسط" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "دامنه" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "مسیر" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "مقدار" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "پیکربندی" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "نام:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "راهنما" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/fi.po b/po/fi.po deleted file mode 100644 index 507b254af..000000000 --- a/po/fi.po +++ /dev/null @@ -1,2571 +0,0 @@ -# Finnish translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-05 09:56+0000\n" -"Last-Translator: Jukka Kauppinen \n" -"Language-Team: Finnish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Lisää torrentti" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Lisää" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Poista torrentti" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Poista" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Poista jaettavat torrentit" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Tyhjennä" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Aloita tai jatka latausta" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Jatka" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Keskeytä torrentti" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Keskeytä" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Siirrä ylös jonossa" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Ylös" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Siirrä alas jonossa" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Alas" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Muuta Delugen asetuksia" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Asetukset" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Liitännäiset" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Tiedosto" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Lisää torrentti" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Lisää _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Poista valmiit" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Muokkaa" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "L_iitännäiset" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrentti" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Näytä" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Työkalupalkki" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "Yksityiskoh_dat" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Sarakkeet" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Koko" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Tila" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Lähteet" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Lataajat" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Latausnopeus" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Lähetysnopeus" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Aikaa jäljellä" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Saatavuus" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Jakosuhde" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Ohje" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Lahjoita rahaa Delugen kehittämiseen" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Lahjoita" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Kotisivu" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_UKK" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Yhteisö" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Auta tämän sovelluksen kielikäännöksessä" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "Käännä _tämä sovellus..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Ajaa ensikäynnistyksen asetusvelhon" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "Aja _asetusvelho" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Ladattu:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Lähetetty:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Lähteet:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Jakosuhde:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Nopeus:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Lataajat:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Jäljellä:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Osia:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Saatavuus:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Tilastot" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Tiedostojen määrä:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Koko:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Seurantapalvelin:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Palvelimen tila:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Seuraava päivitys:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nimi:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Polku:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrentin tiedot" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Tiedot" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Oletko varma, että haluat poistaa valitut torrentit " -"Delugesta?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Poista ladatut tiedostot" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Poista .torrent-tiedosto" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Näytä/Piilota" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Lisää torrentti..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Poista valmiit" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Avaa tiedosto" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Valitse kaikki" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Poista kaikki valinnat" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Älä lataa" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normaali" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Korkea" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Korkein" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge - Päivitä seurantapalvelinlistat" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Avaamasi torrentti on jo Delugessa. Haluatko lisätä vain seurantapalvelimet?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Delugen asetukset" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Kysy erikseen mihin kukin lataus tallennetaan" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Valitse hakemisto" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Tallenna kaikki torrent-tiedostot:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Tallenna kaikki lataukset:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Latauskohde" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Lataa torrent-tiedostot automaattisesti:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Lataa automaattisesti" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "Aktiivisten torrenttien enimmäismäärä. Rajoittamaton: -1." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Samanaikaisesti aktiivisten torrenttien enimmäismäärä:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Valitse tiedostot torrentista ennen latauksen aloittamista" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Näytä vain jos torrentissa on enemmän kuin yksi tiedosto" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" -"Aseta torrentin tiedostojen ensimmäiset ja viimeiset osat ensisijalle" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Käynnistä torrentit keskeytetty-tilassa" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrentit" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Täysi tilanvaraus varaa kaiken torrentin tallentamiseen tarvittavan tilan " -"etukäteen, mikä estää levyn pirstaloitumista" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Käytä täyttä tilanvarausta" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Kompakti tilan varaus varaa tilaa sitä mukaa kuin sitä tarvitaan" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Käytä kompaktia tilanvarausta" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Tilanvaraus" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Lataukset" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Muutokset tulevat voimaan vasta kun Deluge käynnistetään uudelleen." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Mistä:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Mihin:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge ottaa automaattisesti käyttöön eri portin joka kerta." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Satunnaiset portit" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Testaa aktiivinen portti" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktiivinen portti:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "DHT saattaa lisätä aktiivisten yhteyksien määrää." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Ota käyttöön DHT (Mainline)" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT-porttikartoitusprotokolla" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Käyttäjätietojen vaihto" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Paikallinen käyttäjien etsintä" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Verkon lisäasetukset" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Sisääntuleva:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Ei käytössä\n" -"Käytössä\n" -"Pakotettu" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Ulosmenevä:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Suosi kaiken tiedonsiirron salausta" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Taso:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Kättely\n" -"Koko virta\n" -"Jompikumpi" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Salaus" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Verkko" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Siirrä torrentit jonon viimeisiksi, kun ne muuttuvat jakaviksi" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Siirrä uudet torrentit jonossa valmiiden edelle" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Lopeta jakaminen kun jakosuhde ylittää:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Poista enimmäisjakosuhteen saavuttaneet torrentit automaattisesti" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Lopeta torrentin jakaminen, kun jakamisaika ylittää:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Tuntien määrä" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Tyhjennä automaattisesti torrentit, jotka saavuttavat täyden jakoajan" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Jakaminen" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Jakaminen" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Suurin sallittu yhteysyritysten määrä sekunnissa. Suuri arvo saattaa kaataa " -"joitain halpoja reitittimiä. Rajoittamaton: -1." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Yhteysyritysten enimmäismäärä sekunnissa:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Suurin sallittu lähetyspaikkojen määrä kaikille torrenteille. Rajoittamaton: " -"-1." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Suurin sallittu lähetysnopeus kaikille torrenteille. Rajoittamaton: -1." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Suurin sallittu latausnopeus kaikille torrenteille. Rajoittamaton: -1." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Enimmäislatausnopeus (Kt/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Yhteyksien suurin sallittu määrä. Rajoittamaton: -1." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Yhteyksiä enintään:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Enimmäislähetysnopeus (Kt/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Lähetyspaikkojen enimmäismäärä:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Puoliavointen yhteyksien enimmäismäärä. Suuri arvo saattaa kaataa joitain " -"halpoja reitittimiä. Rajoittamaton: -1." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Puoliavointen yhteyksien enimmäismäärä:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Kaistan kokonaiskäyttö" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Suurin sallittu lähetyspaikkojen määrä torrenttia kohden. Rajoittamaton: -1." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Suurin sallittu yhteyksien määrä torrenttia kohden. Rajoittamaton: -1." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Torrenttikohtainen kaistankäyttö" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Kaista" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Vaikuttaa normaaleihin bittorrent-lataajiin" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "P2P-liikenteen välityspalvelin" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Portti" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Palvelin" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Ei mikään\n" -"Socks v4\n" -"Socks v5\n" -"Socks v5 ja todennus\n" -"HTTP\n" -"HTTP ja todennus" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Salasana" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Käyttäjänimi" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Välityspalvelimen tyyppi" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "P2P-välityspalvelin" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Seurantapalvelinten välityspalvelin" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Seurantapalvelinten välityspalvelin" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT-välityspalvelin" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT-välityspalvelin" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Web-jakojen välityspalvelin" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Web-jakojen välityspalvelin" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Välityspalvelimet" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Näytä kuvake ilmoitusalueella" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Pienennä ilmoitusalueelle suljettaessa" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Käynnistä ilmoitusalueelle pienennettynä" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Suojaa ilmoitusalueelle pienennetty Deluge salasanalla" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Salasana:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Ilmoitusalue" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Käytä tarkempaa edistymispalkkia (käyttää hieman enemmän " -"järjestelmäresurseja)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Yksityiskohtainen edistymispalkki" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge tarkistaa palvelimeltamme uusimman version ja ilmoittaa jos sellainen " -"on ilmestynyt." - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Ilmoita uudesta versiosta" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Päivitykset" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Auta meitä parantamaan Delugea lähettämällä meille tiedot koneesi\n" -"Python ja PyGTK -versiosta, käyttöjärjestelmästä ja prosessorityypistä.\n" -"Mitään muuta tietoa ei lähetetä." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Järjestelmän tiedot" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Muut" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Pakota uudelleentarkistus" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Ja_tka" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Keskeytä" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "Poista to_rrentti" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "Seuran_tapalvelin" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Päivitä seurantapalvelin" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Muokkaa seurantapalvelimia" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "Pyydä _scrape-tietoja" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Jono" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "Yl_in" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Ylös" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Alas" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "A_lin" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Avaa hakemisto" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Näytä Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Jatka kaikkia" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Keskeytä kaikki" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Lata_usrajoitus" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Lähet_ysrajoitus" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "Lo_peta" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Muokkaa seurantapalvelimia" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Seurantapalvelinten muokkaus" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge - Tiedoston valinta" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrenttia ei jaeta seurantapalvelimettoman DHT-verkon kautta" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Merkitse yksityiseksi" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Ensikäynnistyksen asetukset" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Tämä asetusvelho auttaa Delugen asetusten säätämisessä. Jos olet uusi " -"Delugen käyttäjä, huomaathan, että suurin osa Delugen toiminnoista on " -"liitännäisten muodossa. Muokkaa-valikon liitännäiset-kondasta pääset " -"valitsemaan haluamasi liitännäiset ja muokkaamaan niiden asetuksia." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge tarvitsee porttivälin, jolta se hakee saapuvia yhteyksiä. " -"Oletusportit bittorrentille ovat 6881-6889, mutta monet Internet-palvelujen " -"tarjoajat ovat sulkeneet nämä portit, joten suosittelemme valitsemaan toisen " -"välin 49152:n ja 65535:n väliltä. Vaihtoehtoisesti voit antaa Delugen valita " -"automaattisesti satunnaisen porttivälin." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "_Käytä satunnaisia portteja" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Haluatko Delugen lataavan tiedostot automaattisesti ennaltamäärättyyn " -"hakemistoon, vai haluatko määrittää lataushakemiston itse joka kerta?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Kysy minulta mihin kukin tiedosto tallennetaan" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Tallenna kaikki tiedostot hakemistoon: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Valitse internet-yhteytesi lähetysnopeus, jota käytetään automaattisten " -"asetus-ehdotusten tekemiseen" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Aktiivisten torrenttien enimmäismäärä:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8kb\n" -"56kb\n" -"64kb\n" -"96kb\n" -"128kb\n" -"192kb\n" -"256kb\n" -"384kb\n" -"512kb\n" -"640kb\n" -"768kb\n" -"1Mb\n" -"2Mb\n" -"10Mb\n" -"20Mb\n" -"40Mb\n" -"50Mb\n" -"100Mb" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Lähetysnopeutesi:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Auta meitä parantamaan Delugea lähettämällä meille tiedot Python- ja PyGTK-" -"\n" -"versiostasi, käyttöjärjestelmästäsi ja prossessorisi tyypistä. Mitään muuta\n" -"tietoa ei lähetetä." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Selaimen käynnistys epäonnistui. Varmista, että python-gnome2-extras on " -"asennettu tai kokeile asettaa LD_LIBRARY_PATH ja MOZILLA_FIVE_HOME-" -"ympäristömuuttujien arvoksi /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "kt/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Rajoittamaton" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktivoitu" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Muu…" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Latausnopeus (kt/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Lähetysnopeus (kt/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge on lukittu" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge on suojattu salasanalla.\n" -"Saadaksesi Deluge-ikkunan esiin ole hyvä ja syötä salasanasi" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Ikuisuus" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Tuntematon" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nimi" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Aikaa jäljellä" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Saatavuus" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Suhde" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Valitse kansio, jonne haluat siirtää torrentin lähteen." - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Poista vanha torrentti?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Keskeytetty %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Jonossa %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Delugesta on saatavilla uudempi versio. Haluatko siirtyä lataussivullemme?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Yhteydet" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Lataus" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Lähetys" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent-ohjelma" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Valitse latauskansio" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Torrentin lisäyksessä tapahtui virhe. On mahdollista, että .torrent-" -"tiedostosi on viallinen." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Tuntematon kaksoiskappaletorrentti-virhe." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Vapaata levytilaa ei ole riittävästi latauksen suorittamiseksi loppuun." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Tilaa tarvitaan:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Tilaa vapaana:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Lisää torrentti osoitteesta" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Anna lisättävän .torrent-tiedoston osoite" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Varoitus - kaikki tämän torrentin ladatut tiedostot poistetaan!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Oletko varma, että haluat poistaa kaikki jaettavat torrentit?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Jonossa" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Tarkistetaan" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Yhdistetään" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Ladataan metatietoja" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Ladataan" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Valmis" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Varataan muistia" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "tavua tarvitaan" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Vapaata levytilaa ei ole riittävästi latauksesi suorittamiseen." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Ilmoitus lähetetty" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Ilmoitus OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Hälytys" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP-koodi" - -#: src/core.py:776 -msgid "times in a row" -msgstr "kertaa peräkkäin" - -#: src/core.py:788 -msgid "Warning" -msgstr "Varoitus" - -#: src/files.py:77 -msgid "Filename" -msgstr "Tiedostonimi" - -#: src/files.py:82 -msgid "Priority" -msgstr "Tärkeys" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Tiedostojen tärkeysastetta voidaan säätää vain kun täysi tilanvaraus on " -"käytössä.\n" -"Ota kompakti tilanvaraus pois käytöstä asetuksissa. Tämän jälkeen poista ja " -"lisää takaisin tämä torrentti." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Liitännäinen" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Käytössä" - -#: src/dialogs.py:445 -#, fuzzy -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Valitse .torrent-tiedosto" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrentti-tiedostot" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Kaikki tiedostot" - -#: src/common.py:88 -msgid "KiB" -msgstr "kt" - -#: src/common.py:91 -msgid "MiB" -msgstr "Mt" - -#: src/common.py:94 -msgid "GiB" -msgstr "Gt" - -#: src/common.py:97 -msgid "TiB" -msgstr "Tt" - -#: src/common.py:99 -msgid "PiB" -msgstr "Pt" - -#: src/common.py:206 -msgid "External command" -msgstr "Ulkoinen komento" - -#: src/common.py:207 -msgid "not found" -msgstr "ei löydy" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Lataa ja ottaa käyttöön IP-estolistoja.\n" -"\n" -"Tällä hetkellä tämä liitännäinen pystyy käsittelemään PeerGuardian\n" -"(binääri ja teksti), SafePeer ja Emule-listoja. PeerGuardian 7zip-" -"tiedostoja\n" -"ei tueta. Tiedostot voidaan määritellä URL:ksi tai paikallisen tiedosto-\n" -"järjestelmän sijainneiksi.\n" -"\n" -"Estolistojen lataussivuille löytyy linkit wikistä:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian teksti (Pakkaamaton)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP-lista (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer teksti (Zip-pakattu)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "URL-osoitetta ei voitu ladata" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Estolistan tiedostoa ei voitu avata" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Väärä tiedoston tyyppi tai virheellinen estolista-tiedosto." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Tuotu" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP:tä" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Estolista" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "kohtaa" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Estolistan URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Lataa uusi estolista välillä" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "päivää" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Ladataan ja asennetaan estolista" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Tuodaan" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Valmis" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Zip-tiedostosta löytyi formaatti-poikkeama:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Odotettiin gzip-tiedostoa, mitä emme saaneet tai tiedosto on mahdollisesti " -"virheellinen. Ole hyvä ja korjaa Estolistan asetukset." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Epäkelpo aloitus" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Epäkelpo eväste" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Epäkelpo versio" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Aseta haluamasi enimmäisjakosuhde jokaiselle torrentille erikseen." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "Haluttu jakosuh_de" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Ei asetettu" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Ei asetettu" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Haluttu jakosuhde" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Tämä näyttää sinulle torrentin lataajat. Näet heistä IP:n, valtion, " -"torrentti-ohjelman, latauksen valmiusprosentin sekä lataus- ja " -"lähetysnopeuden.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP-osoite" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Ohjelma" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "%:a valmiina" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Luo torrentti" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Torrentti luodaan yksittäisestä tiedostosta" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Tiedosto:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Torrentti luodaan hakemistosta" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Hakemisto:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Lähde" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Tallenna torrentti-tiedosto nimellä:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Lataa luotu torrentti heti Delugeen jaettavaksi" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Lisää uusi torrentti jonoon" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrentti-tiedosto" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Seurantapalvelimet" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Web-jaot" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Kommentit" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Tekijä" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Merkitse yksityiseksi" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Mitä pienempiä osat ovat sitä tehokkaampaa tiedonsiirto on, mutta itse " -".torrent-tiedostosta tulee suurempi" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 kt\n" -"64 kt\n" -"128 kt\n" -"256 kt\n" -"512 kt\n" -"1024 kt\n" -"2048 kt\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Osan koko:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Lisäasetukset" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Liitännäinen torrenttien luomiseen" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Uusi torrentti" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Uusi torrentti" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Luo uusi torrentti" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Tallenna tiedosto nimellä..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Torrentille täytyy valita lähde." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Torrentille täytyy valita tallennuspaikka." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Torrentti-ilmoitusten asetukset" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Toista tapahtuma-äänet (tarvitsee pygame:n, ei saatavilla Win32:lle)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Vilkuta ilmoitusalueen kuvaketta" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Näytä ponnahdusikkuna (tarvitsee python-notify:n, ei saatavilla Win32:lle)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Kun torrentti valmistuu, ilmoitusalueen kuvake vilkkuu ja/tai saat " -"ilmoituksen ponnahdusikkunassa" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrentti valmis" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Verkon tilan valvonta\n" -"\n" -"Tekijä: Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Tila: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Tapahtumien kirjauksen asetukset" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Ota käyttöön lokitiedostot" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Lokitiedostot" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Käyttäjä estetty" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Pala valmis" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Palaa ladataan" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Osa valmis" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Tiedoston sijaintia muutettu" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Seurantapalvelimen varoitus" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Seurantapalvelimen hälytys" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Seurantapalvelimen vastaus" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Seurantapalvelimen ilmoitus" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Pikajatkaminen estetty -virhe" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Käyttäjä estetty -virhe" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Hash ei täsmää -virhe" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Tiedostovirhe" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Virheellinen pyyntö" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Käyttäjien viestit" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrentti valmis" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Valitse kirjattavat tapahtumat" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Lisää välilehden, jossa on kirjattaviksi merkittyjen tapahtumien loki.\n" -"\n" -"Tapahtumien viestit kirjataan libtorrent-hälytyksistä. Jos haluat nämä " -"viestit omalla kielelläsi, ilmoita asiasta libtorrentin tekijöille, ei " -"Delugen.\n" -"\n" -"Logit tallennetaan loki-hakemistoon Delugen asetushakemistossa. Tapahtumien " -"viestit yksittäiselle torrentille tallennetaan omaan tiedostoonsa. Nämä " -"tiedostot nimetään vastaavan .torrent tiedoston mukaan. Tapahtumat, jotka " -"eivät liity mihinkään yksittäiseen torrenttiin kirjataan tapahtuman mukaan " -"nimettyihin tiedostoihin, kuten peer_messages.log. Tapahtumien viestit " -"sisältävät myös aikaleiman. Logien tyhjentäminen on käyttäjän vastuulla.\n" -"\n" -"Versiosta 0.2 alkaen:\n" -"-Tapahrumien viestit on nyt lyhennetty Delugessa. Loki tiedostoista ne " -"löytyvät vieläkin täysimittaisina.\n" -"-Uudet tapahtumat ovat nyt ylimpinä.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Tapahtumaloki" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "tapahtumailmoitus: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrentti: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Käyttäjän viesti" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip-osoite: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "ohjelma: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "osan numero: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "tilakoodi: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Kertaa peräkkäin: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "palan numero: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "käyttäjän nopeus: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Aseta haluamasi nopeusrajoitus torrenttikohtaisesti." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrentin _latausnopeus" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrentin lä_hetysnopeus" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrentin lähetysnopeus (kt/s)" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrentin latausnopeus (kt/s)" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Verkkoaktiivisuus-kuvaaja -liitännäinen\n" -"\n" -"Tekijä: Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Kuvaaja" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Edistyminen" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Tiedostoa avattaessa tapahtui virhe." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Tämä liitännäinen näyttää torrentin sisältämät tiedostot ja antaa asettaa " -"niille tärkeysasteet sekä valita mitkä tiedostot ladataan ja mitkä ei.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Tiedostot" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Tämä lisäosa mahdollistaa torrenttien siirtämisen eri kansioon ilman, että " -"täytyisi käsin poistaa, siirtää ja uudelleen lisätä torrentti. Löydät tämän " -"ominaisuuden painamalla hiiren oikeata nappia torrentin kohdalla.\n" -"Lisäksi lisäosa mahdollistaa myös valmistuneiden torrenttien automaattisen " -"siirtämisen uuteen kansioon.\n" -"Huom: Tiedostoja ei voi siirtää muille levyosioille." - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Siirrä torrentti" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Vaihda Torrentin Lähde" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Valitse hakemisto, johon tiedostot siirretään" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Et voi siirtää torrenttia eri osioon. Tarkasta asetuksesi. Et myöskään voi " -"siirtää torrentin tiedostoja samaan hakemistoon, jossa ne jo ovat tai " -"siirtää torrentin tiedostoja ennen kuin niiden lataus on alkanut ja ne on " -"luotu." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Siirrä valmistuneet lataukset:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Tämä liitännäinen mahdollistaa web-jakajien(web-seeds) lisäämisen " -"torrentteihin." - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "Lisää _Web-jako" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Lisää Web-jako" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "Osoite:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Latausraja:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Lähetysraja" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Aktiiviset torrentit:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Lähetyspaikat:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Yhteyksiä enintään:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Ajastimen asetukset" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Vihreä tarkoittaa korkeaa rajoitusta, keltainen matalaa ja punainen " -"pysäytettyä." - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Jos rajoitus on asetettu -1:een, se on rajoittamaton." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Web-käyttöliittymän Asetukset" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Portin numero" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Uusi salasana" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Vahvista uusi salasana" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Pohja" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Painiketyyli" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Välimuistipohja" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Teksti ja kuva" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Ainoastaan kuva" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Ainoastaan teksti" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Varmistettu salasana <> Uusi salasana\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "käännä jotakin" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Valitse URL tai torrentti, älä molempia." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "ei dataa." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "päivitysvälin pitää olla > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# tiedostoista" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Tietoja" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Lisää torrentti" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Käytä" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Päivitä automaattisesti" - -#: plugins/WebUi/scripts/template_strings.py:8 -#, fuzzy -msgid "Ava" -msgstr "Ava" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Asetukset" - -#: plugins/WebUi/scripts/template_strings.py:12 -#, fuzzy -msgid "Debug:Data Dump" -msgstr "Debug:Data Dump" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Poista ladatut tiedostot." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Poista käytöstä" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Ladattu" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Käytä" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Virhe" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Aikaa jäljellä" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Kirjaudu" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Kirjaudu ulos" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Seuraava ilmoitus" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Pois käytöstä" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Väärä salasana, yritä uudelleen" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Keskeytä kaikki" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Osat" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Siirrä alas jonossa" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Sijainti jonossa" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Siirrä ylös jonossa" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Ilmoita uudelleen" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Päivitä sivu joka:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Poista torrentti" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Jatka kaikkia" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Aseta" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Automaattinen uloskirjaus" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Nopeus" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Aloita" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Lähetä" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrentti-lista" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Koko yhteensä" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Seurantapalvelin" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Seurantapalvelimen tila" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Lähetä torrentti" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Lähetetty" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekuntia" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Syöte haetaan automaattisesti, päivitysvälin perusteella." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Syöte pitää päivittää manuaalisesti." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Poissa käytöstä" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Päivitysväli" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Syötteet" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tyyppi" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Syöte" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Tietoja" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Kuviot" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Mistä" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Tuotantokausi" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Jakso" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "-" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Historian rajoitukset" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Ei vastaa" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Vuosi" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Kuukausi" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Päivä" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Testi" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Aseta torrentti jonon ensimmäiseksi." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Keskeytä." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Poista suodatin kun vastaavuus löytyy." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Lataus" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Korvaaja" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Kuvio" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -#, fuzzy -msgid "Link Rewriting" -msgstr "Linkkien uudelleenkirjoitus" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Sisältö tallennetaan Delugen oletushakemistoon. Jos sellaista ei ole " -"asetettu kysytään käyttäjältä." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Delugen oletus" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Sisältö ladataan automaattisesti määritettyyn hakemistoon." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Valitse:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Tuloste" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Suodattimet" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Näytä FlexRSS-ikoni Delugen työkalupalkissa." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Näytä painike työkalupalkissa." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Käyttöliittymä" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Syötteet haetaan ja käsitellään omissa säikeissään. Sovellusta ei estetä, " -"mutta se voi olla epäluotettava." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Säikeistetty (kokeellinen)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Syötteen haku" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Toimialue" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Polku" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Arvo" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Evästeet" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Asetukset" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Hallitse hakuliitännäisiä:" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nimi:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Lisää uusi hakukone syöttämällä nimi ja osoite. Nimeksi syötetään näkyviin " -"tuleva hakukoneen nimi ja osoitteeksi hakusivun URL-osoite. Käyttäjän haku " -"korvaa kaikki ${query}-merkinnät URL-osoitteessa.\n" -"Esimerkiksi Google-haku lisättäisiin syöttämällä:\n" -"Nimi: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Ohje" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Etsi torrentteja tuntemattomana" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Etsittävä merkkijono" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Valitse hakukone" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Hallitse hakukoneita" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Etsi " diff --git a/po/fr.po b/po/fr.po deleted file mode 100644 index 8021f43aa..000000000 --- a/po/fr.po +++ /dev/null @@ -1,2581 +0,0 @@ -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# Éric Lassauge , © 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-09 00:16+0000\n" -"Last-Translator: Axezium \n" -"Language-Team: French \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Ajouter un Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Ajouter" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Supprimer un Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Supprimer" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Effacer les Torrents émetteurs" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Effacer" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Démarrer/Reprendre un torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Reprendre" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Suspendre un Torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Suspendre" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Mettre en file vers le haut" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Vers le haut" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Mettre en file vers le bas" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Vers le bas" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Modifier les préférences" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Préférences" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Modules" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Fichier" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Ajouter un Torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Ajouter un _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Effacer les téléchargements terminés" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Éditer" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "_Modules" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Affichage" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Barre d'outils" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Détails" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Colonnes" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Taille" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "État" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Sources" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Clients" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Vitesse de réception" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Vitesse d'émission" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Temps restant" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Disponibilité" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Taux de partage" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Aide" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Faire un don à l'équipe de développement de Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Faire un don" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "Page d'accueil" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Communauté" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Aider à traduire cette application" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Traduire cette application…" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Lancer l'assistant de configuration" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Lancer l'assistant de configuration" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Téléchargé :" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Envoyé :" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Sources :" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Taux de partage :" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Vitesse :" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Clients :" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Temps restant :" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Pièces :" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Disponibilité :" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistiques" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Nombre de fichiers :" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Taille totale :" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker :" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "État du tracker :" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Prochaine annonce :" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nom :" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Chemin : " - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Infos torrent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Détails" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Êtes vous sûr de vouloir supprimer le(s) torrent(s) " -"sélectionné(s) de Deluge ?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Supprimer les fichiers téléchargés" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Supprimer le fichier .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Afficher/Cacher" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Ajouter un torrent…" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Effacer les torrents terminés" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Ouvrir le fichier" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Tout sélectionner" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Tout déselectionner" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Ne pas télécharger" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normale" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Haute" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "La plus haute" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Fusionner les listes de tracker" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Le torrent est déjà présent dans Deluge, voulez-vous fusionner les listes de " -"tracker ?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Préférences de Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Demander où sauvegarder chaque téléchargement" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Sélectionner un dossier" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Stocker tous les torrents dans :" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Stocker tous les téléchargements dans :" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Répertoire de réception" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Charger automatiquement les torrents contenu dans :" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Chargement automatique" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Le nombre de téléchargements actifs simultanement. Mettre -1 pour illimité." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Nombre maximum de torrents actifs simultanément :" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Choisir les fichiers à télécharger au démarrage" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Montrer seulement si le torrent contient plus d'un fichier" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Télécharger en priorité la première et la dernière pièce" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Démarrer les torrents en pause" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"L'allocation complète pré-alloue tout l'espace requis pour le torrent et " -"permet d'éviter la fragmentation du disque" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Utiliser l'allocation complète" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "L'allocation compacte alloue seulement l'espace nécessaire" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Utiliser l'allocation compacte" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Allocation" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Téléchargements" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Les changements de ces paramètres ne seront pris en compte qu'au prochain " -"démarrage de Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "De :" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "À :" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" -"Deluge choisira à chaque fois automatiquement un port différent à utiliser." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Ports aléatoires" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Tester le port actif" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Port actif :" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"La DHT (Distributed Hash Table) peut augmenter le nombre de connections " -"actives." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Activer la DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "Protocol de mappage de port NAT" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Échange de client" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Recherche locale de client" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Extras réseau" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Entrée :" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Désactivé\n" -"Activé\n" -"Forcé" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Sortie :" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Préférer crypter le flux entier" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Niveau :" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Poignée de main\n" -"Flux complet\n" -"L'un ou l'autre" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Cryptage" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Réseau" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" -"Déplacer les torrents à la fin de la file quand ils passent en partage" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Placer les nouveaux torrents au-dessus des terminés" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Arrêter de partager les torrents quand leur ratio atteint :" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Effacer automatiquement les torrents qui atteignent le ratio maximal" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Arrêter les torrents après un temps de transfert de:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Nombre d'heures" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Effacer automatiquement les torrents terminés une fois que le temps de " -"transfert maximum a été atteint" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Partage" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Partage" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Le nombre maximum de tentatives de connexions par secondes. Une valeur " -"élevée peut faire planter les routeurs bon marchés. Mettre -1 pour illimité." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maximum de tentatives de connexions par seconde :" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "Nombre maximum de slots d'émission. Mettre -1 pour illimité." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Vitesse maximale d'envoi pour tous les torrents. Mettre -1 pour illimitée." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Vitesse maximale de réception pour tous les torrents. Mettre -1 pour " -"illimitée." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Vitesse maximale de téléchargement (Kio/s) :" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Nombre maximum de connexions. Mettre -1 pour illimité." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maximum de connexions :" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Vitesse maximale d'envoi (Kio/s) :" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maximum de slots d'émission :" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Le maximum de connexions à demi-ouvertes. Une valeur élevée peut faire " -"planter certains routeurs bon marché. Mettre -1 pour illimité." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maximum de connexions à demi-ouvertes :" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Réglages généraux de la bande passante" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Le nombre maximal de sessions d'envoi simultanées par torrent. Mettre -1 " -"pour illimité." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Le nombre maximal de connexions par torrent. Mettre -1 pour illimité." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Réglages par torrent de la bande passante" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Bande passante" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Affecte les clients bittorent normaux" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Proxy client" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Serveur" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Aucun\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 + auth.\n" -"HTTP\n" -"HTTP + auth." - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Mot de passe" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Nom d'utilisateur" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Type de proxy" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Proxy client" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Proxy tracker" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Proxy tracker" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Proxy DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Proxy DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Proxy Web Seed" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Proxy Web Seed" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxies" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Activer l'icône dans la barre des tâches" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimiser dans la barre des tâches à la fermeture" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Démarer dans la barre des tâches" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Protéger par un mot de passe" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Mot de passe :" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Barre des tâches" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Utiliser les barres de progression détaillées (utilise sensiblement plus de " -"CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Barres de progression détaillées" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge va vérifier nos serveurs et vous indiquer si une nouvelle version est " -"disponible" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Etre averti des nouvelles versions" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Mises à jour" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Aidez nous à ameliorer Deluge en nous envoyant vos versions de Python\n" -"et de PyGTK, votre OS et votre type de processeur.\n" -"Aucune autre information ne sera transmise." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Informations système" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Divers" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Forcer la vérification" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Re_prendre" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Mettre en pause" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Supprimer le torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "Options du _tracker" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "Act_ualiser le tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Éditer les trackers" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Scrape du Tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Mettre en attente" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Haut" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Monter" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Descendre" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Bas" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Ouvrir le répertoire de destination" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "Afficher Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "Reprendre tout" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "Suspendre tout" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Vitesse limite de réception" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Vitesse limite d'envoi" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "Quitter" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Éditer les trackers" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Édition des trackers" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Sélection des fichiers" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Le torrent ne sera pas distribué sur le réseau décentralisé (DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Utiliser le drapeau privé" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Configuration du premier lancement" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Cet utilitaire va vous aider à configurer Deluge selon vos préférences. Si " -"c'est la première fois que vous utilisez Deluge, veuillez noter que la " -"plupart des fonctionnalités et des capacités de ce logiciel viennent de " -"greffons, auxquels vous pouvez accéder en cliquant sur Greffons dans le menu " -"Edition ou dans la barre d'outils." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge necéssite une série de ports à partir desquels il tentera d'ecouter " -"les connexions entrantes. Les ports par défaut de bittorrent sont 6881-6889, " -"cependant la plupard des fournisseurs d'accès internet bloquent ces ports, " -"vous êtes donc encouragés à utiliser d'autres ports, entre 49152 et 65535. " -"Deluge peut également choisir automatiquement un port aléatoire." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Utiliser un port _aléatoire" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Préferez-vous que Deluge télécharge automatiquement dans un répertoire " -"prédéfini, ou bien choisir à chaque fois le répertoire de destination ?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Demander où sauvegarder chaque fichier" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Stocker tous les téléchargement dans : " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Sélectionnez la vitesse d'émission de votre connexion afin que nous " -"puissions ensuite pré-sélectionner les paramètres ci-dessous." - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maximum de torrents actifs :" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Votre vitesse d'émission :" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Aidez nous à améliorer Deluge en nous envoyant vos versions de Python et de " -"PyGTK, votre OS et votre type de processeur. Aucune autre information ne " -"sera envoyée." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Impossible de détecter le navigateur. Vérifiez que python-gnome2-extras est " -"bien installé ou essayez de changer vos variables LD_LIBRARY_PATH et " -"MOZILLA_FIVE_HOME à /urs/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "Kio/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Illimité" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Activé" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Autres…" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Vitesse de réception (Kio/s) :" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Vitesse d'envoi (Kio/s) :" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge est verrouillé" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge est protégé par un mot de passe.\n" -"Pour afficher Deluge, veuillez entrer votre mot de passe." - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infini" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Inconnu" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nom" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Temps restant" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Dispo." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Ratio" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Choisir un dossier afin de changer la source du torrent" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Supprimer l'ancienne source du torrent?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "En pause %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "En attente %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Une nouvelle version de Deluge est disponible. Souhaitez-vous visiter le " -"site de téléchargement ?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Connexions" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Réception" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Émission" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge - Client Bittorrent" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Choisissez un répertoire de téléchargement" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Une erreur est survenue lors de l'ajout du torrent. Il est possible que le " -"fichier « .torrent » soit corrompu." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Erreur inconnue de doublon de torrent." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Il n'y a pas suffisemment d'espace disque pour compléter le téléchargement." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Espace nécessaire :" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Espace disponible :" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Ajouter un torrent à partir d'une URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Entrez l'URL du « .torrent » à télécharger" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Attention - Tous les fichiers téléchargés pour ce torrent seront supprimés !" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Êtes-vous sur de vouloir supprimer tous les torrents en source ?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "En attente" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Vérification" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Connexion" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Téléchargement des métadonnées" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Téléchargement" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Terminé" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Allocation" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "octets nécessaires" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Il n'y a pas assez d'espace disponible pour finir le téléchargement." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Annonce envoyée" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Annonce valide" - -#: src/core.py:774 -msgid "Alert" -msgstr "Alerte" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "Code HTTP" - -#: src/core.py:776 -msgid "times in a row" -msgstr "fois d'affilée" - -#: src/core.py:788 -msgid "Warning" -msgstr "Attention" - -#: src/files.py:77 -msgid "Filename" -msgstr "Nom de Fichier" - -#: src/files.py:82 -msgid "Priority" -msgstr "Priorité" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Les priorités de fichier ne peuvent être utilisées qu'avec l'allocation " -"complète.\n" -"Veuillez changer vos préférences pour désactiver l'allocation compacte, puis " -"supprimer et rajouter ce torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Greffon" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Activé" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge est un logiciel libre, vous pouvez le redistribuer et/ou le modifier " -"selon les termes de la GNU\n" -"General Public License comme publié par la Free Software Foudation, que ce " -"soit sous sa version 2\n" -"ou une plus récente. Deluge est distribué dans l'espoir qu'il sera utile, " -"mais absoluement SANS AUCUNE GARANTIE.\n" -"Réferez vous à la GNU General Public Licence pour plus de détails. Vous " -"devriez en avoir recu une\n" -"copie avec Deluge, mais si ce n'est pas le cas, écrivez à :\n" -"Free Software Foundation Inc.\n" -"51 Franklin St, Fifth Floor\n" -"Boston, MA 02110\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Sélection d'un « .torrent » à ouvrir" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Fichiers torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Tous les fichiers" - -#: src/common.py:88 -msgid "KiB" -msgstr "Kio" - -#: src/common.py:91 -msgid "MiB" -msgstr "Mio" - -#: src/common.py:94 -msgid "GiB" -msgstr "Gio" - -#: src/common.py:97 -msgid "TiB" -msgstr "Tio" - -#: src/common.py:99 -msgid "PiB" -msgstr "Pio" - -#: src/common.py:206 -msgid "External command" -msgstr "Commande externe" - -#: src/common.py:207 -msgid "not found" -msgstr "non trouvé" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Télécharger et importer diverses listes noires d'IP.\n" -"\n" -"Ce greffon supporte actuellement les listes aux formats\n" -"PeerGuardian (binaire et texte), SafePeer et Emule, mais\n" -"pas les fichiers compressés 7zip de PeerGuardian.\n" -"Vous pouvez utiliser des listes locales ou en ligne.\n" -"\n" -"Une page du wiki référence les sites où télécharger\n" -"des listes noires :\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "P2B PeerGuardian (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "Texte PeerGuardian (Non compressé)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Liste d'IP Emule (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "Texte SafePeer (Zippé)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Impossible de télécharger l'URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "La liste noire ne peut être ouverte" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Mauvais type de fichier ou liste noire corrompue" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importé" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Liste noire" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "entrées" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL de la liste noire" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Télécharger une nouvelle liste noire tous les" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "jours" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Charger et installer une liste noire" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importation" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Terminé" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Exception de format du fichier zip :" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Un fichier n'est pas du type attendu (gzip), ou bien il est corrompu. " -"Veuillez revoir les préferences de la liste noire." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Leader invalide" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Code magique invalide" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Version invalide" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Fixer le ratio pour un torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "Ratio _désiré" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Non réglé" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Non réglé" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Ratio désiré" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Ceci vous montre les pairs associés à chaque torrent et affiche leurs IP, " -"pays, client, pourcentage complété, ainsi que leurs vitesses d'envoi et de " -"réception.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Adresse IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Client" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Pourcentage complété" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Créateur de torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Ce torrent sera créé à partir d'un fichier unique" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Fichier :" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Ce torrent sera créé à partir d'un dossier" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Dossier :" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Source" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Enregistrer le fichier torrent sous :" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Charger ce torrent dans Deluge pour le partager" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Ajouter les nouveaux torrents à la file d'attente" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Fichier torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackers" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Sources web" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Commentaires" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Auteur" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Marquer" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Plus les pièces seront petites, plus les transferts seront efficaces, mais " -"le « .torrent » sera plus gros." - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiO\n" -"64 KiO\n" -"128 KiO\n" -"256 KiO\n" -"512 KiO\n" -"1024 KiO\n" -"2048 KiO\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Taille des pièces :" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Avancé" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Un greffon pour créer des torrents." - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Nouveau torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Nouveau torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Créer un nouveau torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Enregistrer le fichier sous…" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Vous devez sélectionner une source pour ce torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Vous devez indiquer un fichier sous lequel enregistrer le torrent." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Préférences de notification des torrents" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Activer les sons (nécessite pygame, non disponible sur Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Activer l'icône clignotante dans la barre des tâches" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Autoriser les notifications par pop-up (nécessite python-notify, non " -"disponible pour win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Fait clignoter l'icône de la barre des tâches quand un torrent se termine " -"et/ou afficher une info-bulle de notification." - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent terminé" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Greffon de notification de la santé du réseau\n" -"\n" -"Écrit par Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Santé : OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Préférences de la journalisation" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Activer les fichiers de journalisation" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Fichiers de journalisation" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Client bloqué" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Bloc terminé" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Téléchargement d'un bloc" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Pièce terminée" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Fichier déplacé" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Avertissement du tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Alerte du tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Réponse du tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Annonce du tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Erreur de reprise rapide" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Erreur de banissement client" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Erreur de calcul du hash" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Erreur de fichier" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Requête invalide" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Messages des clients" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent terminé" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Sélectionner les évènements à journaliser" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Ajoute un onglet de journalisation d'évènements choisis.\n" -"\n" -"Les messages d'évènement viennent des alertes de libtorrent. Si vous voulez " -"que ces phrases soient traduites dans votre langue, vous aurez à rapporter " -"cela à libtorrent, pas à Deluge.\n" -"\n" -"En ce qui concerne les fichiers log, ils seront enregistrés dans un " -"répertoire log inclus dans le dossier de configuration de Deluge. Les " -"messages d'évènements venant d'un torrent spécifique seront enregistrés sous " -"un nom correspondant à celui du « .torrent ». Les autres messages seront " -"enregistrés dans un fichier nommé selon l'évènement (par ex. " -"peer_message.log).\n" -"Les messages d'évènements incluent une date.\n" -"L'utilisateur doit nettoyer les logs.\n" -"\n" -"v0.2\n" -"Les évènements sont tronqués dans l'affichage, pas dans les logs.\n" -"Les nouveaux évènements sont affichés en premier.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Journal d'évènements" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "message : " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent : " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Message client" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "Adresse IP : " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "Client : " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "Index de la pièce : " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "Code d'état : " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Nombre de fois successives : " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "Index de bloc : " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "vitesse client : " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Fixer la limite de vitesse pour un torrent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Vitesse de _Téléchargement" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Vitesse d'_Envoi" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Vitesse d'envoi (Kio/s) :" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Vitesse de téléchargement (Kio/s) :" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Greffon de graphique d'activité du réseau\n" -"\n" -"Écrit par Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graphique" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progression" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Une erreur s'est produite lors du lancement du fichier" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Ce greffon vous montre les fichiers contenu dans le torrent et vous permet " -"de régler les priorités ainsi que de choisir lesquels vous désirez ou non " -"télécharger.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Fichiers" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Ce greffon permet de changer le répertoire du torrent sans avoir à retirer " -"puis rajouter le torrent. On trouve cette fonctionnalité en effectuant un " -"clic droit sur un torrent.\n" -"De plus, il permet de changer automatiquement de répertoire les torrents " -"finis.\n" -"Note : les fichiers doivent restés sur la même partition" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Déplacer le torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Changer la source du Torrent" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Choisissez un répertoire où déplacer les fichiers" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Vous ne pouvez pas déplacer un torrent vers une partition différente. " -"Veuillez verifier vos préférences. Il est également impossible de déplacer " -"un torrent vers un dossier où il se situe déjà, ou avant qu'au moins l'un de " -"ses fichiers n'ait été créé." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Déplacer les téléchargements terminés vers :" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Ce greffon permet aux utilisateurs d'ajouter un web seed à leurs torrents." - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Ajouter un web seed" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Ajouter un Web Seed" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL :" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Limite en téléchargement :" - -#: plugins/Scheduler/plugin.py:114 -#, fuzzy -msgid "Upload limit:" -msgstr "Limite d'envoie" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Torrents actifs :" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Slots d'émission:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Nombre maximum de connexions:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Paramètres du plannificateur" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"La valeur en vert est la limite haute, celle en jaune la valeur basse et " -"celle en rouge est la valeur stoppée." - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Une limite de -1 signifie illimité." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Configuration de l'interface Web" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Port n°" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nouveau mot de passe" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Nouveau mot de passe (confirmation)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Modèle" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Style des bouttons" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Mettre les modèles en cache" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Texte et images" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Images seulement" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Texte seulement" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Mot de passe confirmé <> Nouveau mot de passe\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "traduire quelquechose" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Choisissez une url ou un torrent, pas les deux." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "pas de données." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "le raffraichissement doit être >0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "Nombre de fichiers" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "À propos" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Ajouter un torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Appliquer" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Raffraichissement auto :" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Disp" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Config" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Data Dump" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Supprimer les fichiers téléchargés" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Désactiver" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Téléchargé" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Activer" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Erreur" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Temps restant" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Nom d'utilisateur" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Se déconnecter" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Prochaine annonce" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Désactivé" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Mot de passe invalide, essayez encore." - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Tout mettre en pause" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Pièces" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Ajouter à la suite" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Position dans la file d'attente" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Ajouter en premier" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Re-annonce" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Raffraichir la page tous les :" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Supprimer le torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Reprendre tout" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Définir" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Regler la temporisation" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Vitesse" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Démarrer" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Envoyer" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Liste des torrents" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Taille Totale" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Etat du Tracker" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Envoyer un torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Envoyé" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "URL" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "secondes" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"Les flux seront relevés automatiquement, selon l'intervalle de mise à jour." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Les flux doivent être rafraichis manuellement." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Désactivé" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Intervalle de mise à jour" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Flux" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Type" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Flux" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Information" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Filtres" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "De" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Saison" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Épisode" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Pendant" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Historique des restrictions" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Ne correspond pas" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Année" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Mois" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Jour" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Inserer le torrent en haut de la file." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Mettre en pause." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Supprimer le filtre losqu'il correspond." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Téléchargement" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Remplacement" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Motif" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Réécriture du lien" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Le contenu sera sauvegardé dans le répertoire par défaut de Deluge. S'il n'a " -"pas été défini un message d'invite apparaîtra." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Paramètres par défaut de Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" -"Le contenu sera automatiquement téléchargé dans le répertoire spécifié." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Choisissez :" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Sortie" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtres" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Afficher une icône de FluxRSS dans la barre d'outils de Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Montrer les boutton dans la barre d'outils." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interface" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Les flux vont etre récupérés et analysés. L'application ne sera pas bloquée, " -"mais cela peut ne pas être fiable." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Enfilés (experimental)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Relevage des flux" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domaine" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Chemin" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Valeur" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Configuration" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Gérer les greffons de recherche" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nom :" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Ajouter un moteur de recherche en entrant un nom et une URL. Pour le nom, " -"utiliser celui du moteur de recherche. Pour l'URL, entrer celle de la page " -"de recherche. La recherche de l'utilisateur remplacera toutes les " -"occurrences de ${querry} dans l'URL.\n" -"Par exemple, une recherche Google sera :\n" -"Nom : Google\n" -"URL : http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Aide" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Rechercher des torrents anonymement" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Chaîne de recherche" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Choississez un moteur de recherche" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Gérer les moteurs de recherche" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Recherche " diff --git a/po/fy.po b/po/fy.po deleted file mode 100644 index a6bddbbf7..000000000 --- a/po/fy.po +++ /dev/null @@ -1,2388 +0,0 @@ -# Frisian translation for deluge -# Copyright (c) 2008 Rosetta Contributors and Canonical Ltd 2008 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2008. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-08 08:51+0000\n" -"Last-Translator: Wander Nauta \n" -"Language-Team: Frisian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Torrent tavoegje" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Tavoegje" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Torrent fuortsmite" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Fuortsmite" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Siedende torrents opromje" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Opromje" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Torrent starte as ferfetsje" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Ferfetsje" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Torrent skoftsje" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Skoftsje" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Torrent omheech yn rij" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Omheech" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Torrent omleech yn rij" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Omleech" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Foarkarren" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Ynfoegtapassings" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Bestân" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "Torrent t_afoege" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "_URL tafoege" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Foltooiden opromje" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "Be_wurkje" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Ynfoe_gtapassings" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "By_ld" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "Ar_kbalken" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Details" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Kolommen" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Grutte" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Steat" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Seeders" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Peers" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Delhelsnelheid" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Uploadsnelheid" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Oerblieuwende tiid" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Beskikberheid" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Ratio" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Help" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "Tússide" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Gemienskip" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Helpe dit programma oer te setten" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "Dizze applikaasje oerse_tte..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "De earste-kear konfiguraasjeassistent útfiere" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "Konfiguraasjeassistent útfiere" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Oantal triemen:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Trackersteat:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Earstfolgjende oankondiging:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Namme:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/gl.po b/po/gl.po deleted file mode 100644 index cdc929b00..000000000 --- a/po/gl.po +++ /dev/null @@ -1,2423 +0,0 @@ -# Galician translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-15 19:51+0000\n" -"Last-Translator: maaark \n" -"Language-Team: Galician \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Engadir Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Engadir" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Eliminar Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Eliminar" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Borrar torrents finalizados" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Borrar" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Iniciar o continuar torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Continuar" - -#: glade/delugegtk.glade:93 -#, fuzzy -msgid "Pause Torrent" -msgstr "Deter torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Deter" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Subir Torrent na Cola" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Subir" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Baixar Torrent na Cola" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Abaixo" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Cambiar as preferencias de Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Preferencias" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugins" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Ficheiro" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Engadir Torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Engadir _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "Limpar _Completos" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Editar" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_gins" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Ver" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Barra de Ferramentas" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detalles" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Columnas" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Tamaño" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Estado" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Parceiros Completos" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Parceiros" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Velocidade de Descarga" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Velocidade de Subida" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Tempo Restante" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Dispoñibilidade" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Taxa de Compartición" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "A_xuda" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Axuda a traducir esta aplicación" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Traducir esta aplicación..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Arrancar o titorial de configuración inicial" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Descargado:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Subido:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Parceiros Completos:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Taxa de Compartición:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Velocidade:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Parceiros:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Tempo Estimado:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Partes:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Dispoñibilidade:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Estatísticas" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Tamaño Total:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Rastrexador:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Estado do Rastrexador:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Próximo Anuncio:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nome:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Camiño:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Información de Torrent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detalles" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Estás seguro de que queres eliminar os torrent(s) " -"seleccionados de Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Eliminar os ficheiros descargados" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Eliminar o ficheiro .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Amosar/Agochar" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Engadir un Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Limpar Rematados" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Seleccionar Todo" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Deseleccionar Todo" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Non descargar" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Alta" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "A máis alta" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Lista de Rastrexadores de Deluge" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "o Torrent xa estaba en Deluge,queres añadir á lsita de tracker?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Preferencias de Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Preguntar onde gardar cada descarga" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Selecciona un Cartafol" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Almacenar todo-los arquivos torrent en:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Gardar todas as descargas en:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Lugar de descarga" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Cargar automáticamente todo-los torrent en:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"O número de torrents activos que Deluge manexará. Poñer a -1 para que sexa " -"ilimitado." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Máximo número de torrents activos simultaneamente" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Descargas" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Nota - Os cambios para estas configuracións só serán aplicados a próxima " -"vez que reinicie Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Dende:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Para:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Probar Porto Activo" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Porto Activo:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"A tabla hash distribuída pode mellorar a cantidade de conexións activas." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Activar a DHT Oficial" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "Protocolo de Tradución de Portos NAT" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Extras de Rede" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Entrante:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Desactivado\n" -"Activado\n" -"Forzado" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Saínte:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Preferir cifrar todo o fluxo" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Nivel:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Cifrado" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Rede" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Poñer torrents ao final da cola cando se complete a descarga" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" -"Parar de compartir torrents cando a súa taxa de compartición alcance:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Compartindo" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Compartindo" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Velocidade máxima de subida para todos os torrents. Pon -1 para que sexa " -"ilimitada." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Velocidade máxima de baixada para todos os torrents. Pon -1 para que sexa " -"ilimitada." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Velocidade Máxima de descarga (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" -"Número máximo de conexións permitidas. Pon -1 para que sexa ilimitado." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Número Máximo de Conexións:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Velocidade Máxima de Subida (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Afecta parceiros de bittorrent normais" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Proxy de Parceiros" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Porto" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Servidor" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Ningún\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 con Aut.\n" -"HTTP\n" -"HTTP con Aut." - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Contrasinal" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Nome de usuario" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Tipo de Proxy" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Proxy do Rastrexador" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Proxy da DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Habilitar a icona na bandexa do sistema" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimizar á bandexa do sistema ao pechar" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Protexer con contrasinal a bandexa do sistema" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Contrasinal:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Bandexa do Sistema" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Outros" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Eliminar Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Actualizar Rastrexador" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Editar Rastrexadores" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "S_ubir" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Baixar" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Último" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Amosar Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Saír" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Ilimitado" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Outros..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge está bloqueado" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge está protexido cunha contrasinal.\n" -"Para amosar a fiestra de Deluge, por favor introduce o teu contrasinal." - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infinito" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Descoñecido" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nome" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Tempo Estimado" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Taxa" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Detido %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Conexións" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Descarga" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Subida" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Cliente de Bittorrent Deluge" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Escolla un directorio de descarga" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Ocorreu un error mentres se intentaba engadir o torrent. É posible que o " -"ficheiro .torrent esté corrupto." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Espazo necesario:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Espazo dispoñible:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Engadir torrent dende a URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Introduce a URL do .torrent a descargar" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Advertencia - borraranse todos os ficheiros descargados deste torrent !" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "En cola" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Comprobando" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Descargando" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Rematado" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Asignando" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes necesarios" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Non hai suficiente espacio libre para rematar a descarga." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "Node de ficheiro" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Activo" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Escolla un ficheiro .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Ficheiros Torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Todos os ficheiros" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "días" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Enderezo IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Cliente" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Porcentaxe Completada" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Error de arquivo" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Solicitude Inválida" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progreso" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Ficheiros" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Mover descargas completas a:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Rañuras de Subida:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Seguinte Anuncio" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Partes" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Comezar" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Tamaño Total" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Estado do Tracker" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "segundos" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Administrar Plugins de Busca" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nome:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Engade un novo motor de busqueda introducindo o nome e a URL. Para o nom, " -"introduce o nome do motor de búsqueda que queres usar. Paraa URL, introduce " -"a url da páxina. A query de búsqueda do usuario será remplazada por ${query} " -"na URL.\n" -"Por exemplo, unha búsqueda en Google será así:\n" -"Nome: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Axuda" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Xestionar Motores" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Busca " diff --git a/po/he.po b/po/he.po deleted file mode 100644 index 465532a9b..000000000 --- a/po/he.po +++ /dev/null @@ -1,2531 +0,0 @@ -# Hebrew translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-29 09:53+0000\n" -"Last-Translator: Mark Krapivner \n" -"Language-Team: Hebrew \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "הוסף טורנט" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "הוספה" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "הסר טורנט" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "הסר" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "פינוי טורנטים משתפים" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "ניקוי" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "התחל או הפעל מחדש טורנט" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "המשך" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "השהה טורנט" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "השהייה" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "העלה עדיפות" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "למעלה" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "הורד עדיפות" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "למטה" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "שנה הגדרות" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "הגדרות" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "תוספים" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_קובץ" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_הוסף טורנט" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "_הוסף כתובת" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_פינוי טורנטים שהושלמו" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_עריכה" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "הר_חבות" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_טורנט" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_הצגה" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_סרגל כלים" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_פרטים" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_עמודות" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "נפח" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "מצב" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "מפיצים" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "משתפים" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "מהירות הורדה" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "מהירות העלאה" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "זמן נותר" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "זמינות" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "יחס שיתוף" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_עזרה" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "תרום לפיתוח דלוג'" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_תרום" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_דף הבית" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_שאלות נפוצות" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_קהילה" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "עזרו בתרגום התוכנה" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "תרגם את התוכנה הזו" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "מריץ את אשף ההפעלה הראשונה" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "הרצת אשף ההפעלה הראשונה" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "ירד:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "הועלה:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "מפיצים:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "יחס שיתוף:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "‏מהירות:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "משתפים:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "זמן הורדה משוער:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "חלקים:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "זמינות:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "סטטיסטיקה" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# מהקבצים:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "גודל כולל:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "טראקר:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "מצב טראקר:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "קריאה באה:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "שם:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "נתיב:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "מידע על הטורנט" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "פרטים" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"אתם בטוחים שאתם רוצים להסיר את הטורנט(ים)?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "מחק קבצים שהורדו" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "מחק קובץ .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "הצג/הסתר" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "הוסף טורנט..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "הסר טורנטים שהושלמו" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_פתיחת קובץ" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "בחר הכל" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "בטל סימון" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "לא להוריד" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "נורמלי" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "גבוה" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "הגבוה ביותר" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "מיזוג רשימות טראקרים" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "נימצא שהטורנט כבר קיים, האם תירצו למזג בין רשימות הטקאקר?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "העדפות התוכנה" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "שאל בכל פעם לאן להוריד" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "בחר תיקייה" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "אחסון כל קבצי הטורנט ב:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "שמור את כל ההורדות ל:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "מיקום ההורדה" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "טעינה אוטומטית של קבצי טורנט ב:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "טעינה אוטומטית" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "מספר הטורנטים הפעילים שירוצו ב- בתוכנה. -1 עבור מספר בלתי מוגבל." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "מספר הטורנטים הפעילים בו זמנית המקסימלי:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "הפעל אפשרות בחירת קבצים לטורנטים לפני הטעינה" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "הצג רק אם לטורנט יש יותר מקובץ 1" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "קבע סדרי עדיפויות לחלקים הראשונים והאחרונים של הטורנט" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "התחל טורנטים במצב מושהה" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "טורנטים" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"הקצאה מלאה מקצה מראש את כל המיקום הדרוש בשביל הטורנט ומונעת פיצול " -"(fragmentaion) מיותר של הדיסק." - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "שימוש בהקצאה מלאה" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "אחסון קומפקטי יוקצא רק לפי הצורך" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "שימוש באחסון קומפקטי" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "הקצאה" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "הורדות" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "הערה - השינויים יחולו אחרי הפעלה מחדש של התוכנה." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "מ-:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "ל-:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge יבחר אוטומטית פורט שונה לשימוש בכל פעם." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "פורטים רנדומליים" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "בדוק פורט פעיל" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "פורט פעיל:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "סיפוק טבלת גיבוב (hash table) יכול לשפר את כמות החיבורים הפעילים." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "הפעל הזרקת DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Plug - Play אוניברסלי" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "פרוטוקול מיפוי פורט NAT" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "חילופי מקורות" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "זיהוי משתפים מקומיים" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "הרחבות רשת" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "כלפי פנים:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"כבוי\n" -"מופעל\n" -"מאולץ" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "כלפי חוץ:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "העדפה להצפין את כל הזרם" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "רמה:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"לחיצת יד\n" -"שטף מלא\n" -"שניהם" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "הצפנה" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "רשת" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "הורד טורנטים לסוף הרשימה בזמן השיתוף" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "העלה עדיפות לטורנטים חדשים מעל אלה שהושלמו" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "הפסק לשתף טורנטים כשיחס השיתוף מגיע ל:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "פנה אוטומטית טורנטים שהגיעו ליחס השיתוף המקסימלי" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "חדל לזרוע טורנטים כאשר זמן הזריעה מגיע ל:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "מספר השעות" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "מחק טורנטים המגיעים לזמן הזרעה מקסימלי באופן אוטומטי" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "משתף" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "שיתוף" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"מספר ניסיונות התחברות מקסימלי לשנייה. ערך גבוהה עלול לגרום לנתבים זולים " -"לקרוס. רשמו -1 עבור בלתי מוגבל." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "מספר ניסיונות התחברות מקסימלי לשנייה:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "מספר נקודות העלאה מקסימלי עבור כל הטורנטים. -1 עבור בלתי מוגבל" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "מהירות העלאה מקסימלית עבור כל הטורנטים. -1 עבור ללא הגבלה." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "מהירות הורדה מקסימלית עבור כל הטורנטים. -1 עבור ללא הגבלה." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "מהירות הורדה מקסימלית (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "מספר החיבורים המקסימלי המותר. -1 עבור מהירות בלתי מוגבלת." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "מקסימום חיבורים:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "מהירות העלאה מקסימלית (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "מקסימום נקודות העלאה:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"מקסימום חיבורים חצי-פתוחים. ערך גבוהה עלול לגרום לנתבים ישנים לקרוס. -1 עבור " -"בלתי מוגבל." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "מקסימום חיבורים חצי-פתוחים:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "שימוש כללי בתעבורה" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "מקסימום נקודות העלאה לכל טורנט. -1 עבור בלתי מוגבל." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "מספר המקסימלי של חיבורים לכל טורנט. -1 עבור בלתי מוגבל." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "שימוש בתעבורה לכל טורנט" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "רוחב פס" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "משפיע על חיבורי ביטורנט רגילים" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "פרוקסי למשתפים" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "מספר פורט" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "שרת" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"ללא\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "סיסמה" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "שם משתמש" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "סוג פרוקסי" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "פרוקסי למשתפים" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "פרוקסי לטראקר" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "פרוקסי הטראקר" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "פרוקסי DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "פרוקסי DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "פרוקסי לרשת מקורות" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "פרוקסי לרשת מקורות" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "פרוקסים" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "הפעל סמל במגש מערכת" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "הקטן למגש המערכת בסגירה" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "התחל במגש המערכת" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "הגן בסיסמה על הסמל במגש המערכת" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "סיסמה:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "מגש מערכת" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "שימוש בפס התקדמות מתקדם (דורש קצת יותר CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "פס התקדמות מפורט" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "Deluge יבדוק עכשיו את השרתים ויודיע לכם אם שוחררה גרסה חדשה" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "הודיעו לי כאשר יש גרסה חדשה" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "עדכונים" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"עזרו לנו להשתפר על ידי שליחת גרסאות ה-Python וה-PyGTK \n" -"שלכם, מערכת ההפעלה וסוג המעבד. כמובן ששום מידע\n" -"נוסף לא נשלח." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "מידע מערכת" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "אחר" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_הכרח בדיקה" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "המ_שך" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_השהייה" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_הסר טורנט" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_אפשרויות טראקר" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_עדכן טראקר" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_ערוך טראקרים" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_קיבוץ טראקר" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_העבר לתור" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_עליון" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_למעלה" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_למטה" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_תחתון" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_פתח תיקייה מכילה" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_הצג" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_הפעל מחדש הכל" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_עצור הכל" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_הגבלת מהירות הורדה" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_הגבלת מהירות העלאה" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_סיים" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "עריכת טראקרים" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "עריכת טראקרים" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "בחירת קבצים של Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "הטורנט לא יופץ על ללא רשת טראקרים (DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "קבעית דגל פרטי" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "הגדרות הפעלה ראשונה" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"האשף יעזור לכם להגדיר את Deluge בצורה הכי טובה עבורכם. אם אתם חדשים ל-" -"Deluge, שימו לב שרוב התכונות והפונקציות של התכנה באים בצורת הרחבות, שניתן " -"לגשת אליהם על ידי לחיצה על הרחבות בתפריט העריכה או על סרגל הכלים." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge צריכה תווך של פורטים שינסו לתקשר אם חיבורים נכנסים. כברירת מחדל " -"הפורטים לביטורנט הן 6881-6889, אבל, רוב ה-ISP חוסמים את הפורטים האלו, אז " -"מומלץ לבחור באחרים, בין 49152 ו-65535. או לחלופין אתם יכולים לקבוע ש-Deluge " -"יבחר פורטים אקראיים עבורכם." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "שימוש בפורטים _אקראיים" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"האם תרצו ש-Deluge אוטומטית יעביר את ההורדות למיקום מוגדר מראש, או שתרצו " -"לבחור מיקום לפני כל הורדה?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "שאל לאן לשמור כל קובץ" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "אחסון ההורדות ב: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"אנא בחרו את מהירות ההעלאה של החיבור שלכם, זה ישמש כדי לתת הצעות עבור " -"ההגדרות למטה" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "מקסימום טורנטים פעילים:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "גבול מהירות העלאה שלכם:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_עזרו לנו לשפר את Deluge על ידי שליחת הגרסה של Python ואת הגרסה של PyGTK,\n" -"מערכת ההפעלה וסוג המעבד. שם מידע אחר\n" -"לא ישלח." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"הפעלת הדפדפן נכשלה. נא לוודא ש-python-gnome2-extras מותקן או לנסות לקבוע את " -"ערכי המערכת LD_LIBRARY_PATH ו-MOZILLA_FIVE_HOME ל-/usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "ללא הגבלה" - -#: src/interface.py:325 -msgid "Activated" -msgstr "מופעל" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "אחר...‏" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "מהירות הורדה (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "מהירות העלאה (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "התוכנה נעולה" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"התוכנה מוגנת בסיסמה.\n" -"כדי לפתוח את חלון התוכנה עליכם להכניס סיסמה" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "אינסוף" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "לא ידוע" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "שם" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "זמן משוער" - -#: src/interface.py:651 -msgid "Avail." -msgstr "זמינות" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "יחס" - -#: src/interface.py:760 -#, fuzzy -msgid "Choose a directory to switch torrent source to" -msgstr "בחר ספרייה אליה יועברו הקבצים" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "האם למחוק את הקבצים המקוריים?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "הושהה %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "%s בתור" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "יש גרסה חדשה של Deluge. אתם רוצים לעבור לעמוד ההורדות שלנו?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "חיבורים" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "הורדה" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "העלאה" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge - תוכנת ביטורנט" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "בחר תיקייה להורדות" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"התרחשה שגיאה כשניסיתם להוסיף את הטורנט. יכול להיות שקובץ הטורנט שלכם פגום." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "שגיאת טורנט כפול לא ידועה." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "אין די מקום פנוי כדי להשלים את ההורדה." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "מקום פנוי נידרש:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "מקום פנוי זמין:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "הוסף טורנט מכתובת" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "הכנס את הכתובת של הטורנט להורדה" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "אזהרה - כל הקבצים שהורדו בשביל הטורנט הזה ימחקו!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "למחוק את כל הטורנטים המשתפים?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "ממתין" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "בודק" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "מתחבר" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "מוריד Metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "מוריד" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "הסתיים" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "מקצה" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "בייטים נדרשים" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "אין מספיק מקום פנוי כדי להשלים את ההורדה." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "קריאה נשלחה" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "קריאה תקינה" - -#: src/core.py:774 -msgid "Alert" -msgstr "התראה" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "קוד HTTP" - -#: src/core.py:776 -msgid "times in a row" -msgstr "פעמים בשורה" - -#: src/core.py:788 -msgid "Warning" -msgstr "אזהרה" - -#: src/files.py:77 -msgid "Filename" -msgstr "שם קובץ" - -#: src/files.py:82 -msgid "Priority" -msgstr "עדיפות" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"ניתן להשתמש בעדיפות קבצים רק באחסון מלא.\n" -"אנא ערכו את ההגדרות שלכם ובטלו את האחסון הקומפקטי, אז הסירו והוסיפו מחדש את " -"הטורנט." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "תוסף" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "מופעל" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge זו היא תוכנה חופשית: אתה יכול להפיצה ו/או\n" -"לשנותה על פי תנאי הרישיון הציבורי הכללי של גנו כפי שהם\n" -"מפורסמים על-ידי קרן התוכנה החופשית, בין אם גרסה 3 של הרישיון\n" -"או (לבחירתך) כל גרסה מאוחרת יותר.\n" -"Deluge מופצת בתקווה שתהיה שימושית אבל בלא כל אחריות; בלא\n" -"אפילו אחריות משתמעת למסחריות או התאמה לשימוש מסוים. \n" -"ראה את הרישיון הציבורי הכללי של גנו לפרטים נוספים.\n" -"אמור היית לקבל עותק של הרישיון הציבורי הכללי של גנו ביחד עם Deluge. \n" -"אם לא, כיתבו למוסד לתוכנה חופשית., 51 Franklin St, Fifth Floor, Boston, MA " -"02110-\n" -"1301 USA." - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "בחר קובץ טורנט" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "קבצי טורנט" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "כל הקבצים" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "פקודה חיצונית" - -#: src/common.py:207 -msgid "not found" -msgstr "לא נמצא" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"הורדה ויבוא רשימות IP חסומות.\n" -"\n" -"כרגע ההרחבה הזו יכולה לעבוד עם PeerGuardian (בינארי וטקסט),\n" -"רשימות SafePeer ו-Emule. קבצי PeerGuardian 7zip לא נתמכים. ניתן לציים " -"כתובות של קבצים או מיקום על מערכת הקבצים המקומית.\n" -"\n" -"עמוד שמכוון לאתרים עם רשימות שחורות של כתובות IP זמין\n" -"בויקי:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "טקסט PeerGuardian (לא-מכווץ)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "רשימת IP מאימיול (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer טקסט (Zipped)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "הורדת הכתובת לא הצליחה" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "פתיחת קובץ של רשימה שחורה לא הצליח" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "סוג קובץ שגוי או הקובץ פגום." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "ייובא" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "רשימת חסומים" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "רשומות" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "כתובת רשימה שחורה" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "הורד רשימת חסימות חדשב כל" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "ימים" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "טעינה והתקנה של רשימה שחורה" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "מייבא" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "הושלם" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "התקבלה תבנית ליוצאים מן הכלל בקובץ הזיפ" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"ציפינו לקבל קובץ gzip, אך קיבלנו קובץ אחר או שהקובץ פגום. אנא ערוך את הגדרות " -"רשימת החסימות שלך." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "leader לא תקין" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "קוד מג'יק לא תקין" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "גרסה לא תקינה" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "קיבוע את יחס השיתוף הרצוי לטורנט." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_יחס שיתוף רצוי" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_לא נקבע" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "לא נקבע" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "יחס שיתוף רצוי" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"זה מציג את המשתפים המשויכים עם כל טורנט ומראה לכם את כתובת ה-IP, המדינה, " -"לקוח הביטורנט, האחוז שהושלם ואת מהירויות ההעלאה וההורדה.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "כתובת IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "תוכנה" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "אחוז הושלם" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "יוצר טורנטים" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "הטורנט הזה ייווצר מקובץ בודד" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "קובץ:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "הטורנט הזה ייווצר תיקייה" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "תיקייה:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "מקור" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "שמור קובץ טוררנט בשם:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "טען הטורנט לתוך התוכנה רק עבור שיתוף" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "הוסף טורנטים חדשים לתור" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "קובץ טורנט" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "טראקרים" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "משתפי רשת" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "תגובות" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "יוצר" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "קביעת דגל פרטי" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"אם החלקים יהיו קטנים יותר, כך ההעברה תהיה יעילה יותר, אבל קובץ הטורנט עצמו " -"יהיה גדול יותר" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "גודל החלק:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "מתקדם" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "תוסף ליצירת טורנטים" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_טורנט חדש" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "טורנט חדש" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "יצירת טורנט חדש" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "שמור קובץ בשם..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "חובה לבחור מקור עבור הטורנט." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "אתם חייבים לבחור קובץ כדי לשמור את הטורנט כך." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "העדפות התראות טורנט" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "אפשר צליל מאורע (דורש שימוש ב-pygame, לא זמין על-Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "הפעל הבהוב צלמית מגש המערכת" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "להפעיל התראת חלון-קובץ (python-notify נידרש, לא זמין על Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "הצלמית במגש המערכת תהבהב כשתסתיים הורדה ו/או תהייה התראה בחלון קובץ" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "התטורנט הושלם" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"תוסף פקח תקינות הרשת\n" -"\n" -"נכתב על ידי Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[תקינות הרשת: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "העדפות יוצר הלוגים" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "אפשר קבצי לוג" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "קבצי לוג" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "משתף נחסם" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "בלוק שהסתיים" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "בלוק יורד" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "חלקים שהושלמו" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "האחסון הועבר" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "אזהרת טראקר" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "התראת טראקר" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "תגובת טראקר" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "הכרזת טראקר" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "תקלה - חידוש מזורז נדחה" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "שגיאת חסימת משתף" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "שגיאת גיבוב שנכשל" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "שגיעת קובץ" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "בקשה לא תקפה" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "הודעות ממשתפים" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "טורנט הסתיים" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "בחרו אירוע עבור הלוג" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"לשונית עם לוג של אירועים נבחרים.\n" -"\n" -"התראות עם אירועים מגיעים מהתראות libtorrent.\n" -"אם אתם רוצים שהמחרוזות יתורגמו לשפה המקומית שלכם,\n" -"אז תצטרכו לדווח על הבעיה שלכם ל-libtorrent, לא ל-deluge.\n" -"\n" -"בנוקע לקבצי הלוג, קבצי הלוג ישמרו בתיקיית \n" -"הלוגים בתיקיית ההגדרות של deluge. הודעות אירועים\n" -"עבור טורנטים ספציפיים ישמרו כקבצי לוג אינדיבידואלים\n" -"עם השם של קובץ הטורנט המיועד. הודעות שלא נועדו \n" -"עבור שום טורנט ספציפי ישמרו לפי האירוע שהם מתעדים\n" -"(לדוגמה peer_messages.log).\n" -"הודעות אירועים בקבצי הלוג יכללו גם את התאריך.\n" -"המשתמש אחראי על פינוי הלוגים.\n" -"\n" -"הכל מ-v0.2\n" -"אירועים מוצגים קטועים בתצוגה. קבצי לוג לא.\n" -"אירועים חדשים כאת יוצר למעלה.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "רישום האירועים" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "הודעת אירוע " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "טורנט: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "הודעת משתף" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "כתובת IP: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "לקוח: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "אינדקס חלקים: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "קוד מצב: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "פעמים בשורה: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "אינדקס בלוקים: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "מהירות משתף: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "קבעו את גבול המהירות עבור כל טורנט." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "מהירות _הורדת טורנט" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "מהירות העלאת _טורנט" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "מהירות העלאת טורנט (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "מהירות הורדת טורנט (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"תוסף תרשים פעילות הרשת\n" -"\n" -"נכתב על ידי Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "גרף" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "התקדמות" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "ארעה שגיאה בנסיון להפעיל את הקובץ." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"ההרחבה מראה לכם את הקבצים בתוך טורנט ומאפשר לכם לקבוע להם את העדיפות של " -"הקבצים ולבחור את אלו שאתם רוצים או לא רוצים להוריד.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "קבצים" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"תוסף זה מאפשר למשתמשים להעביר את הטורנט לספריה אחרת, מבלי להסיר ולהוסיף מחדש " -"אותו. ניתן להשתמש בתכונה זו על ידי קליק ימני על הטורנט.\n" -"מעבר לכך, התוסף מאפשר להעביר לספריה נפרדת את כל הטורנטים שהורדתם הסתיימה.\n" -"הערה: כרגע ניתן להעביר קבצים רק לאותה מחיצה." - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_העברת טורנט" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_החלף את מקור הטורנט" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "בחרו בתיקייה שיועברו עליה הקבצים" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"אי אפשר להעביר טורנטים למחיצה אחרת. נא לבדוק את ההעדפות שלכם. גם, אי אפשר " -"להעביר קבצי טורנט לאותה תיקייה בא הם נמצאים או להעביר קבצי טורנט לפני שאחד " -"מהקבצים שלו נוצר." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "העבר הורדות שהושלמו ל:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "ההרחבה הזאת מאפשרת למשתמשים להוסיף משתפי רשת לטורנטים שלהם" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_הוספת שיתוף רשת" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "הוספת משתף רשת" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "הגבלת הורדה:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "הגבלת העלאה:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "טורנטים פעילים:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "נקודות העלאה:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "מספר חיבורים מירבי:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "הגדרות המתזמן" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "ירוק זה גבולות גבוהים, צהוב זה גבולות נמוכים ואדום זה נעצר" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "הוא גבול ניקבע ל -1 , אז זה ללא הגבלה." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "הגדרות ממשק רשת" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "מספר פורט" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "סיסמה חדשה" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "סיסמה חדשה(אימות)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "תבנית" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "סיגנון כפתור" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "שמור תבניות במטמון" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "טקסט ותמונה" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "רק תמונה" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "רק טקסט" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "אימות סיסמה <> סיסמה חדשה\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "תרגום משהו" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "בחר בכתובת או בטורנט, לא שניהם." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "אין נתונים." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "הרענון חייב להיות > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# מהקבצים" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "אודות" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "הוסף טורנט" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "החל" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "רענון אוטומטי:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "זמינות" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "הגדרות" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Data Dump" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "למחוק קבצים שירדו." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "כיבוי" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "ירד" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "הפעל" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "שגיאה" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "זמן הורדה משוער" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "כניסה" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "יציאה" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "הכרזה הבאה" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "כבוי" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "הסיסמה לא תקינה,נסו שוב" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "השהה הכל" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "חלקים" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "למטה בתור" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "מיקום בתור" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "למעלה בתור" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "להכריז מחדש" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "לרענן את העמוד כל:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "הסר טורנט" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "הפעל הכל" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "קבע" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "קביעת פסק-זמן" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "מהירות" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "התחלה" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "טען" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "רשימת טורנטים" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "גודל כולל:" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "טראקר" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "סטטוס טראקר" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "העלאת טורנט" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "הועלה" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "כתובת" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "שניות" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "הערוצים יעודכנו אוטומטית, לפי זמן העדכון." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "ערוצים יעודכנו ידנית." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "כבוי" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "זמן עדכון" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "כתובת" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "ערוצים" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "סוג" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "ערוץ" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "מידע" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "תבניות" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "מאת" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "עונה" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "פרק" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "באמצעות" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "הגבלת היסטוריה" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "לא להתאים" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "שנה" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "חודש" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "יום" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "בדיקה" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "הכנסת הטורנט לראש התור." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "קביעת המצב כמושעה" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "מחק את הפילטר לאחר שנמצאה התאמה." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "הורדה" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "תחליף" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "תבנית" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "שכתוב לינקים" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"תוכן ישמר לתוך תיקיית ברירת המחדל של Deluge, או תופיע הודעה במידה ולא ניקבע." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "ברירת מחדל של Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "התוכן ירד אוטומטית לתיקייה מוגדרת." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "בחר:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "פלט" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "פילטרים" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "הצגת הסמל של FlexRSS בסרגל הכלים של Deluge." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "הצגת הכפתור בסרגל הכלים." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "ממשק" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"הזנות יאוחזרו וינותחו בשרשורים שלהן. התוכנה לא תחסם, אך היא עלולה שלא ליהיות " -"מהימנת." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "פתילים נפרדים (ניסיוני)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "אחזור ערוצים" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "דומיין" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "נתיב" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "ערך" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "קוקיז" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "הגדרות" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "הגדרת מנועי חיפוש" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "שם:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"הוסיפו מנוע חיפוש חדש על ידי הזנת השם והכתובת של המנוע. איפה שהשם, הזינו את " -"שם המנוע שאתם רוצים להשתמש בו. בכתובת הזינו את כתובת עמוד החיפוש. מחרוזת " -"החיפוש שלכם תירשם במקום בו יהיה הטקסט ${query} בשדה הכתובת.\n" -"לדוגמה, חיפוש בגוגל יראה כך:\n" -"שם: גוגל\n" -"כתובת: http://www.google.co.il/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "עזרה" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "חפש אחר טורנטים בעילום שם" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "מחרוזת חיפוש" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "בחר מנוע" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "ניהול מנועי חיפוש" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "חיפוש " diff --git a/po/hi.po b/po/hi.po deleted file mode 100644 index 97ffc1de6..000000000 --- a/po/hi.po +++ /dev/null @@ -1,2399 +0,0 @@ -# Hindi translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-12 13:14+0000\n" -"Last-Translator: Sukarn Maini \n" -"Language-Team: Hindi \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -#, fuzzy -msgid "Add Torrent" -msgstr "टॉरेन्ट जोड़ें" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -#, fuzzy -msgid "Add" -msgstr "जोड़ें" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -#, fuzzy -msgid "Remove Torrent" -msgstr "टॉरेन्ट हटईयें" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "हटईयें" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "खाली करें" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "टॉरेन्ट पुनरारंभ करे" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "पुनरारंभ करे" - -#: glade/delugegtk.glade:93 -#, fuzzy -msgid "Pause Torrent" -msgstr "टॉरेन्ट ठहरें" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "ठहरें" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "टॉरेन्ट कतार में ऊपर करें" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "ऊपर" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "टॉरेन्ट कतार में नीचे करें" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "नीचे" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "डिलय्ज की पसन्द बदलें" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "पसन्द" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "प्लग-इन्स" - -#: glade/delugegtk.glade:186 -#, fuzzy -msgid "_File" -msgstr "संचिका (_F)" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "टॉरेन्ट जोडें" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -#, fuzzy -msgid "_Edit" -msgstr "संपादन (_E)" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "" - -#: glade/delugegtk.glade:309 -#, fuzzy -msgid "_View" -msgstr "देखें (_V)" - -#: glade/delugegtk.glade:317 -#, fuzzy -msgid "_Toolbar" -msgstr "उपकरण-पट्टी (_T)" - -#: glade/delugegtk.glade:326 -#, fuzzy -msgid "_Details" -msgstr "विवरण (_D)" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -#, fuzzy -msgid "Size" -msgstr "माप" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -#, fuzzy -msgid "Status" -msgstr "प्रस्थिति" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "पीयर्स" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "मदद (_H)" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "नाम:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr " पथ" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "विवरण" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "दिखाएँ / छुपाएँ" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "संचिका खोलें (_O)" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "सभी चुनें" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "सभी अचयनित" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "सामान्य" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "उच्च" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "उच्चतम" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "एक फ़ोल्डर चुनें" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "डाउनलोड्स" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "द्वारा:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "प्रति:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "स्तरः" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "नेटवर्क" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "बेंडविड्थ" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "पोर्ट" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "सर्वर" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "पासवर्ड" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "उपयोक्ता नाम" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "पासवर्ड:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "अन्य" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "ठहरें (_P)" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "शीर्ष (_T)" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "ऊपर (_U)" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "नीचे (_D)" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "नीचे (_B)" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "बाहर (_Q)" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "असीमित" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "अन्य..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "अनंत" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "अज्ञात" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "नाम" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "अनुपात" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "संबंधन" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "डाउनलोड" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "अपलोड" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "जोड़ रहा है" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "डाउनलोड किया जा रहा है" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "पूर्ण" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "अलर्ट" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "चेतावनी" - -#: src/files.py:77 -msgid "Filename" -msgstr "फ़ाइलनाम" - -#: src/files.py:82 -msgid "Priority" -msgstr "प्राथमिकता" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "प्लगिन" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "सभी फ़ाइलें" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "निर्यात कर रहा है" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "पूर्ण" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "आईपी पता" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "क्लाएंट" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "फ़ाइलः" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "फ़ोल्डर:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "फ़ाइल इस रुप में सहेजें..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "घटना लॉग" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "ग्राफ" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "फ़ाइलें" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "यूआरएल:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "सांचा" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "सिर्फ पाठ" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "के बारे में" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "लागू करें" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "निष्क्रिय करें" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "सक्रिय करें" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "त्रुटि" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "लागिन" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "लॉग आउट" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "बंद" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "सेट" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "गति" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "प्रारंभ" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "जमा करें" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "कुल आकार" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "यूआरएल" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "सेकण्ड" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "अक्षम" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "यूआरएल" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "फीड्स" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "प्रकार" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "फीड" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "सूचना" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "से" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "वर्ष" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "महीना" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "दिन" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "बदला" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "पैटर्न" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "आउटपुट" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "फ़िल्टर्स" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "डोमेन" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "पथ" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "मान" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "कुकीज़" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "विन्यास" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "नाम:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "मदद" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/hr.po b/po/hr.po deleted file mode 100644 index 4df93c00a..000000000 --- a/po/hr.po +++ /dev/null @@ -1,2485 +0,0 @@ -# Croatian translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-03-02 20:13+0000\n" -"Last-Translator: Tomislav Plavčić \n" -"Language-Team: Croatian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Dodaj Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Dodaj" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Ukloni Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Izbriši/Ukloni" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Ukloni torrente koji se siju" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Očisti" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Pokreni ili nastavi torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Nastavi" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pauziraj torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pauziraj" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Pomakni Torrent Gore" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Gore" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Pomakni Torrent Dolje" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Dolje" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Promijeni Deluge Postavke" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Postavke" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Dodatci" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Datoteka" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Dodaj Torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Dodaj _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Ukoni Završene Torrente" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Uredi" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Dod_atci" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Pogled" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Traka s alatima" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detalji" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Stupci" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Veličina" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Status" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Seederi" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Točke" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Dolazna Brzina" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Odlazna Brzina" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Preostalo Vrijeme" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Dostupnost" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Udio u Dijeljenju" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Pomoć" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Pomozite prevesti ovu aplikaciju" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Prevedi Ovu Aplikaciju..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Pokreće čarobnjaka za konfiguriranje" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "Pokreni konfiguracijskog čarobnjaka" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Preuzeto Podataka:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Poslano Podataka:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Sijači:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Omjer primljenog i danog:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Brzina:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Točke:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "ETA:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Dijelovi:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Dostupnost:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistike" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "broj datoteka" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Ukupna Veličina:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Sistem za praćenje torrent datoteka:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Status sistema za praćenje torrent datoteka:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Slijedeće objavljivanje :" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Ime:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Putanja:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrent Informacije" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detalji" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Jeste li sigurni da želite ukloniti slijedeći/e " -"torrent(e) iz Delugea?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Obriši preuzete datoteke" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Obriši .torrent datoteku" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Pokaži/Sakrij" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Dodaj Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Makni Završene" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Otvori datoteku" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Odaberi sve" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Odznači sve" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Nemoj skidati" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normalni" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Visoko" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Najviše" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge Spajanje Liste Sistema za Praćenje Torrent Datoteka" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent se već nalazi u Delugeu, želite li spojiti listu sistema za praćenje " -"torrent datoteka?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge Postavke" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Pitaj gdje spremiti sve preuzeto" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Odaberite mapu" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Spremi sve datoteke sa ekstenzijom \".torrent\" u:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Spremi sve preuzeto u:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Lokacija/Mapa za preuzimanje datoteka" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Broj aktivnih torrenta koje će Deluge skidati. Postavite na -1 za " -"neograničen broj." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maksimalan broj istovremeno aktivnih torrenta:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Omogući selekciju datoteka unutar torrenta prije učitavanja" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Prikaži samo ako torrent ima više od 1 datoteke" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Prioritiziraj prve i zadnje komade datoteka u torentu" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Pokreni torrente u pauziranom stanju" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrenti" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Puna alokacija odmah zauzima sav prostor potreban za torrent i spriječava " -"fragmentaciju diska" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Koristi punu alokaciju" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Kompaktna alokacija zauzima potreban prostor prema potrebi" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Koristi kompaktnu alokaciju" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Alokacija" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Preuzimanja" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Molim obratite pozornost - Promjene na ove postavke će biti primjenjene " -"kada Deluge bude ponovno pokrenut." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Od:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Do:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge će automatski odabrati različiti port svaki put." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Nasumični Portovi" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Testiraj Aktivni Port" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktivni Port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Distribuirana tablica raspršivanja može poboljšati broj aktivnih konekcija." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Koristi Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Univerzalno Ukopčaj i Igraj" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "Protokol za pridruživanje NAT Portova" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Ekstra dodaci za mrežu" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Dolazni:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Isključen\n" -"Uključen\n" -"Prisiljen" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Izlazni:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Poželjno enkriptiranje cijelog toka" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Razina:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Enkripcija" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Mreža" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Postavi torrente na dno liste kad se počnu sijati" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Postavi nove torrente iznad završenih" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Prestani sijati torrente kada njihov omjer dosegne:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Automatski počisti torrente koji su postigli maksimalni omjer primljenih i " -"danih podataka" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Sijanje" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Sijem" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Maksimalni broj uploadova za sve torrente. Postavite na -1 za neograničeno." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Makismalna izlazna brzina za sve torrente. Postavite na -1 za neograničeno." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Makismalna ulazna brzina za sve torrente. Postavite na -1 za neograničeno." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maksimalna Dolazna Brzina (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" -"Maksimalan broj dopuštenih konekcija. Postavite na -1 za neograničeno." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maksimalan Broj Konekcija:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maksimalna Izlazna Brzina (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maksimalni broj slotova za slanje:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Globalno zauzeće propusnosti" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Maksimalni broj slotova za slanje po torentu. Postavi na -1 za neograničeno" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Maksimalni broj konekcija po torentu. Postavi na -1 za neograničeno." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Zauzeće propusnosti po torentu" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Propusnost" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Utječe na regularne bittorent točke" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Proxy poslužitelj za bittorent točke" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Poslužitelj" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Nijedan\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 s Autorizacijom\n" -"HTTP\n" -"HTTP s Autorizacijom" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Lozinka" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Korisničko ime" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Tip proxy poslužitelja" - -#: glade/preferences_dialog.glade:1782 -#, fuzzy -msgid "Peer Proxy" -msgstr "Peer proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Proxy za sistem praćenja torrenta" - -#: glade/preferences_dialog.glade:1977 -#, fuzzy -msgid "Tracker Proxy" -msgstr "Tracker proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Uključi ikonu na sistemskoj traci" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimiziraj u sistemsku traku pri zatvaranju" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Zaštiti sistemsku traku sa lozinkom" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Lozinka:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Sistemska Traka" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge će provjeriti naše servere i prijaviti ako je izdana novija verzija" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Budi upozoren na nove verzije" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Nadogradnje" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Pomognite nam da unaprijedimo Deluge tako što nam šaljete verzije Pythona i " -"PyGTK\n" -"koje koristite. OS i vrstu procesora. Druge informacije\n" -"se ne šalju." - -#: glade/preferences_dialog.glade:2688 -#, fuzzy -msgid "System Information" -msgstr "Informacije sistema" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Ostalo" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Na_stavi" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Zaustavi" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Ukloni Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Osvježi sistem za praćenje torrenta" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Editiraj sisteme za praćenje torrenta" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Red" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Vrh" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Gore" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Dolje" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Dno" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Pokaži Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Izlaz" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Želite li da Deluge automatski snima na predefiniranu lokaciju ili želite " -"svaki puta odrediti lokaciju?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Pitaj gdje snimiti svaku datoteku" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Snimaj sve datoteke u: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maksimalni broj aktivnih torrenta:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Neograničen" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktivirano" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Ostalo..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Dolazna Brzina (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Izlazna Brzina (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge je zaključan" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge je zaključan sa lozinkom.\n" -"Kako biste prikazali Deluge prozor molim vas unesite lozinku" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Beskonačno" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Nepoznato" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Ime" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Omjer" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Pauzirano %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Postoji novija verzija Deluge-a. Želite li otvoriti našu stranicu za " -"skidanje?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Veze" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Preuzimanje" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Slanje" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent Client" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Izaberite mapu za preuzimanje" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Dogodila se pogreška tijekom dodavanja torrenta. Moguće je da je .torrent " -"datoteka oštećena." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Nepoznata torrent pogreška." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Ne postoji dovoljno slobodnog prostora za dovršenje vašeg downloada." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Potreban diskovni prostor:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Slobodan diskovni prostor:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Dodaj torrent iz URL-a" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Unesite URL torrenta koji želite preuzeti" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Upozorenje - sve preuzete datoteke iz ovog torrenta će biti pobrisane!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Čeka na red" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Provjera" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Spajanje" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Preuzimam Metapodatke" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Preuzimanje" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Dovršeno" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Alociram" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bajtova potrebno" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" -"Nema dovoljno mjesta na tvrdom disku za završetak procesa preuzimanja " -"datoteka." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Najava poslana" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Najava OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Upozorenje" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP kod" - -#: src/core.py:776 -msgid "times in a row" -msgstr "puta u redu" - -#: src/core.py:788 -msgid "Warning" -msgstr "Upozorenje" - -#: src/files.py:77 -msgid "Filename" -msgstr "Naziv datoteke" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioritet" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Dodatak" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Uključeno" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Izaberite .torrent datoteku" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent datoteke" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Sve datoteke" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "Eksterna naredba" - -#: src/common.py:207 -msgid "not found" -msgstr "nije pronađeno" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Preuzimanje i uvoz raznih IP lista za blokiranje.\n" -"\n" -"Trenutačno ovaj dodatak prima PeerGuardian format (binarni i tekstualni),\n" -"SafePeer i Emule liste. PeerGuardian 7zip format nije podržan.\n" -"Datoteke možete navesti kao URL ili lokacije na lokalnom datotečnom\n" -"sustavu.\n" -"\n" -"Web stranica sa početnim uputama za liste za blokiranje dostupna je\n" -"na wikiju:\n" -"\n" -"https://translations.launchpad.net/deluge/trunk/+pots/deluge\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Tekst (Nekomprimirano)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP list (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SAfePeer Tekst (Zipano)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "URL nije mogao biti preuzet" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Datoteka liste za blokiranje nije mogla biti otvorena" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Uvezeno" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP-ovi" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Lista za blokiranje" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "unosi" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL liste za blokiranje" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dan" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Punjenje i instalacija liste za blokiranje" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Uvoz" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Završeno" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Neispravni vođa" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Neispravni magični kod" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Neispravna verzija" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Postavite željeni omjer za torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Željeni Omjer" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Nije Postavljeno" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Nije Postavljeno" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Željeni Omjer" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP Adresa" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klijent" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Gotovi Postotak" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrent Kreator" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Ovaj torrent će biti napravljen od jedne datoteke" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Datoteka:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Ovaj torrent će biti napravljen od mape" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Mapa:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Izvor" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Spasi Torrent Datoteku Kao:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Uvezi ovaj torrent u Deluge za sijanje" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Dodaj novi torrent u red" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent Datoteka" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Serveri za praćenje torrenta" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Komentari" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Postavi privatnu zastavicu" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Što su dijelovi manje veličine, to će biti efikasniji transfer podatakai, " -"ali će \".torrent\" datoteka biti veća" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Veličina Komada:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Napredno" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Dodatak za pravljenje torrenta" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Novi Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Novi Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Napravi Novi Torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Spremiti datoteku kao..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Morate izabrati izvor za torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Morate izabrati datoteku kako biste mogli sačuvati torrent." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Uključi zvukove (zahtjeva pygame, nije raspoloživo na Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent završen" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Dodatak Monitor Zdravlja Mreže\n" -"\n" -"Napisao Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Zdravlje: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Komad preuzet" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Greška datoteke" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Neispravan zahtjev" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent završen" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Zapisnik" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip adresa: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "klijent: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "status: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "brzina točke: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Dodatak Graf Mrežne Aktivnosti\n" -"\n" -"Napisao Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graf" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Napredak" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Greška prilikom pokretanja datoteke." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Datoteke" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Odaberi direktorij za premještanje datoteka" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Premjesti preuzete podatke na:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Izlazni slotovi:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Postavke planera" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Ako je limit postavljen na -1 tada je neograničeno." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUi konfiguracija" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Broj porta" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nova lozinka" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Nova lozinka(potvrda)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Predložak" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Stil dugmadi" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Tekst i slika" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Samo slika" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Samo tekst" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Potvrda lozinke <> Nova lozinka\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "prevedi nešto" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Odaberi url ili torrent, ne oboje." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "nema podataka." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# datoteka" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "O programu..." - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Dodaj torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Primjeni" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Konfiguracija" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Obriši preuzete datoteke." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Onemogući" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Preuzeto" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Uključi" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Greška" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Korisničko ime" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Odjava" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Iduća najava" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Isključeno" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Kriva lozinka, pokušajte ponovno" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pauziraj sve" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Komadi" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Pomakni u redu dolje" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Pozicija u redu" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Pomakni u redu gore" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Ponovno najavi" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Osvježi stranicu svakih:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Ukloni torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Nastavi sve" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Postavi" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Brzina" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Pokreni" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Pošalji" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Lista torrenta" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Ukupna veličina" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekunda" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Isključeno" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Interval ažuriranja" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Kanali" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Vrsta" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Kanal" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informacije" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Uzorci" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Od" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Sezona" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Epizoda" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Ne odgovara" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Godina" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Mjesec" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Dan" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Dodaj torrent na vrh reda" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Postavi stanje na pauzirano." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Preuzimanje" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Zamjena" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Uzorak" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge uobičajeno" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Odaberi:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Izlaz" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filteri" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Pokaži dugme na alatnoj traci." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Sučelje" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domena" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Putanja" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Vrijednost" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Kolačići" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Konfiguracija" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Postavke Dodataka za Pretraživanje:" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Ime:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Dodajte novu tražilicu unosom Naziva i URL-a. Za Naziv, unesite ime " -"tražilice. Za URL, unesite adresu web stranice tražilice. Korisnikova " -"pretraga će zamijeniti sva pojavljivanja ${query} u URL-u.\n" -"Na primjer, Google pretraga bi bila:\n" -"Naziv: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Pomoć" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Niz za pretraživanje" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Izaberite Tražilicu" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Postavke Tražilica" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Pretraži " diff --git a/po/hu.po b/po/hu.po deleted file mode 100644 index eab6abf61..000000000 --- a/po/hu.po +++ /dev/null @@ -1,2529 +0,0 @@ -# translation of hu.po to -# Hungarian translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: hu\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-26 13:37+0000\n" -"Last-Translator: gergo86 \n" -"Language-Team: Hungarian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Torrent hozzáadása" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Hozzáadás" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Torrent eltávolítása" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Eltávolítás" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Befejezett torrentek törlése" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Tisztítás" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Torrent folytatása vagy megállítása" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Folytatás" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Torrent megállítása" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Megállítás" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Feljebb a listán" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Feljebb" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Lejjebb a listán" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Lejjebb" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Deluge beállításainak módosítása" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Beállítások" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Bővítmények" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Fájl" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "Hozzáadás _fájlból" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Hozzáadás _URL-ből" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "Befejezettek tör_lése" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "Sz_erkesztés" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Bő_vítmények" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Nézet" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "Eszköz_tár" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Részletek" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Oszlopok" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Méret" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Állapot" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Források" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Partnerek" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Letöltés sebessége" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Feltöltés sebessége" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Hátralévő idő" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Elérhetőség" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Megosztási arány" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Segítség" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Támogatás a Deluge fejlesztőinek" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Támogatás" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Kezdőlap" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_GYIK" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Közösség" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Segítség a program lefordításában" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Segítek a program fordításában" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Elindítja a beállítás varázslót" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "Beállítás _varázsló futtatása" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Letöltve:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Feltöltve:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Források:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Megosztási arány:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Sebesség:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Partnerek:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Becsült hátralévő idő:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Darabok:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Elérhetőség:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statisztika" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Fájlok száma:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Teljes méret:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Tracker állapota:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Következő bejelentés:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Név:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Útvonal:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrent információ" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Részletek" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Biztos, hogy el akarod távolítani a kiválasztott " -"torrenteket?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Letöltött fájlok törlése" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr ".torrent fájl törlése" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Megjelenítés/elrejtés" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Torrent hozzáadása..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Befejezettek törlése" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "Fájl meg_nyitása" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Összes Kijelölése" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Összes kijelölés megszüntetése" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Ne legyen letöltve" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normál" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Magas" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Legmagasabb" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge Letöltési Tracker Listája" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"A torrent már fel van véve a Deluge-ba, kívánja egyesíteni a tracker " -"listákat?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge beállítások" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Letöltés helyének megkérdezése minden letöltéskor" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Válasszon egy mappát" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Összes torrent fájl tárolása itt:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Letöltések tárolása itt:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Letöltések helye" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Torrentek automatikus betöltése innen:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Automatikus betöltés" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "Aktív torrentek száma. Korlátlanért -1." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Egyidőben aktív torrentek maximális száma" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Letöltendő fájlok kiválasztása betöltéskor" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Csak akkor mutassa, ha a torrent egynél több fájlt tartalmaz" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Az első és az utolsó darabot töltse először" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Torrentek indítása megállított állapotban" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrentek" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Előre lefoglalja a szükséges területet, így megelőzi a lemez töredezését" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Teljes lefoglalás használata" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Csak annyi helyet foglal, amennyit már letöltött" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Terület lefoglalása menet közben" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Terület Lefoglalása" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Letöltések" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Vegye figyelembe, hogy ezek a beállítások csak a Deluge következő " -"indításakor lépnek életbe" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Kezdet:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Vég:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "A Deluge minden indításkor másik portot fog használni." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Véletlenszerű portok" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Aktív port tesztelése" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktív port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Trackeren kívüli kliensek engedélyezése." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "DHT engedélyezése" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Port Mapping Protocol" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Peer cserélés" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Helyi peer keresése" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Hálózati kiegészítők" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Bejövő:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Tiltott\n" -"Engedélyezett\n" -"Erőltetett" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Kimenő:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Teljes forgalom titkosítása" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Szint" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Kézfogás\n" -"Teljes folyam\n" -"Bármelyik" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Titkosítás" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Hálózat" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "A befejezett torrentek kerüljenek a lista végére" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Az új torrentek kerüljenek a lista elejére" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Megosztás befejezése ha az arány:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Torrentek automatikus törlése ha elérik a kívánt megosztási arányt" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "A torrentek seedelésének megszakítása, ha a seedelt idő eléri:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Órák száma" - -#: glade/preferences_dialog.glade:1142 -#, fuzzy -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Automatikusan törölje a torrenteket ha azok elérik a maximum seedelési időt" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Megosztás" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Megosztás" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Maximum kapcsolódási próbálkozások száma egyetlen másodpercen belül. Magas " -"értékre állítva pár olcsó router összeomlását okozhatja. Végtelenhez állítsd " -"-1 -re." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Másodpercenkénti maximum kapcsolódási kísérlet" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "Feltöltési szálak maximális száma. Korlátlanhoz -1." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "A torrentek maximális feltöltési sebessége. Korlátlanhoz -1." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "A torrentek maximális letöltési sebessége. Korlátlanhoz -1." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maximális letöltési sebesség (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Megengedett kapcsolatok maximális száma. Korlátlanhoz -1." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Kapcsolatok maximális száma:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maximális feltöltési sebesség (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Feltöltési szálak maximális száma:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Maximum félig-nyitott kapcsolatok. Magas értékre állítva pár olcsó router " -"összeomlását okozhatja. Végtelenhez állítsd -1 -re." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maximum félig-nyitott kapcsolatok:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Sávszélesség kihasználása" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "Feltöltési szálak maximális száma torrentenként. Korlátlanhoz -1." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Kapcsolatok maximális száma torrentenként. Korlátlanhoz -1." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Sávszélesség kihasználása torrentenként" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Sávszélesség" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Kihat a szabályos bittorent letöltőkre" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Partner proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Kiszolgáló" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Nincs\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 jelszóval\n" -"HTTP\n" -"HTTP jelszóval" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Jelszó" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Felhasználónév" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxy típusa" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Partner proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Tracker proxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Tracker proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxyk" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Ikon megjelenítése az értesítési területen" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimalizáskor menjen az értesítési területre" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Indítás a tálcán" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Tálca jelszavas védelme" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Jelszó:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Tálca" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"A fejlettebb folyamatjelző csík használata (kissé nagyobb CPU/RAM " -"felhasználás)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Részletes folyamatjelző" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"A Deluge ellenőrzi a szervereket majd tájékoztat ha újabb verzió jelent meg." - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Figyelmeztessen ha új verzió jelent meg" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Frissítések" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Segíts tökéletesíteni a Deluge-t azzal hogy elküldöd nekünk\n" -" a Python -od és a PyGTK-d verzió számát, az oprendszered\n" -" és a processzorod típusát. Egyéb információ nem lesz elküldve." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Rendszer Információ" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Egyéb" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "Gyors _Újraellenőrzés" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "In_dítás" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Megszakítás" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "Torrent _Eltávolítása" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Tracker Beállítások" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "Tracker Frissítése" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "Tracker Szerkesztése" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "Tracker Scrape" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Várólista" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Elejére" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Feljebb" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Lejjebb" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Végére" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "Torrent _Mappájának Megnyitása" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "Deluge _Mutatása" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "Mindet _Elindít" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "Mindet _Megállít" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Letöltési sebességkorlátozás" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Feltöltési sebességkorlátozás" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Kilépés" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Tracker Szerkesztése" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Tracker Szerkesztés" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge Fájl Választás" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "A torrent nem lesz elérhető a DHT hálózatával" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Privát tulajdonság beállítása" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Első indítás varázsló" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Ez a varázsló segít neked beállítani a Deluge-t. Ha még nem ismernéd a " -"Deluge-t tudnod kell, hogy a legtöbb funkció bővítmények segítségével érhető " -"el, amit a Szerkesztés Bővítmények menüpontjában vagy az eszköztár " -"Bővítmények gombjával állíthatsz be." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"A Deluge-nak kell néhány port amin a bejövő kapcsolatokat fogadja. Az " -"alapértelmezett tartomány a 6881-6889, de ezt sok helyen tiltják, ezért " -"ajánlott másikat választani a 49152-65535 tartományból. De akár a Deluge is " -"kiválaszhat neked egy véletlenszerű portot." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "_Véletlenszerű Portok" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Szeretnéd ha a Deluge mindig ugyanoda töltsön le vagy minden letöltésnél más " -"helyet szeretnél használni?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Letöltéskor választom ki a helyet" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Letöltések tárolása itt: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Válaszd ki a feltöltési sebességed, hogy az annak megfelelő értékeket " -"állíthassam be." - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Aktív torrentek maximális száma:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Feltöltési sebességed:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Segíts tökéletesíteni a Deluge-t azzal, hogy elküldöd nekünk\n" -" a Python-od és a PyGTK-d verzió számát , az oprendszered \n" -"és a processzorod típusát. Egyéb információ nem lesz elküldve." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Nem található böngésző. Bizonyosodjon meg róla, hogy a python-gnome2-extras " -"fel van telepítve vagy próbálja meg beállítani az LD_LIBRARY_PATH és " -"MOZILLA_FIVE_HOM környezeti változókat /usr/lib/firefox -hoz." - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Korlátlan" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktív" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Egyéb..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Letöltés sebessége (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Feltöltés sebessége (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge zárolva van" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"A Deluge jelszóval van védve.\n" -"Add meg a jelszavad a folytatáshoz" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Végtelen" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Ismeretlen" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Név" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Hátralévő idő" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Elérhetőség" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Arány" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -#, fuzzy -msgid "Delete the old torrent source?" -msgstr "Törölöd a régen letöltött torrent fájlokat?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Megállítva %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "%s sorbaállítva" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "Újabb verzió jelent meg. Szeretnél a letöltő oldalra ugrani?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Kapcsolatok" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Letöltés" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Feltöltés" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent-kliens" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Válassza ki a letöltés helyét" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Hiba történt a torrent hozzáadásakor. Lehet, hogy a .torrent fájl sérült." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Ismeretlen dupla torrent hiba." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Nincs elegendő hely a lemezen a letöltéshez." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Szükséges hely:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Szabad hely:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Torrent hozzáadása URL-ből" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "A .torrent fájl helye" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Figyelem - a torrenthez tartozó összes fájl törölve lesz!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Biztos, hogy eltávolítja az összes készforrás torrentet?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Várakozik" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Ellenőrzés" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Csatlakozás" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Metaadat letöltése" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Letöltés" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Befejezve" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Helyfoglalás" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bájt van hátra" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Nincs elegendő hely a lemezen a letöltéshez." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Bejelentés elküldve" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Bejelentés rendben" - -#: src/core.py:774 -msgid "Alert" -msgstr "Hiba" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP kód" - -#: src/core.py:776 -msgid "times in a row" -msgstr "próbálkozások száma" - -#: src/core.py:788 -msgid "Warning" -msgstr "Figyelem" - -#: src/files.py:77 -msgid "Filename" -msgstr "Fájlnév" - -#: src/files.py:82 -msgid "Priority" -msgstr "Elsőbbség" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"A fájlok elsőbbségének kiválasztása csak teljes terület lefoglalásakor " -"használható.\n" -"Állítsd át a terült lefoglalást majd add újra hozzá a torrentet." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Bővítmény" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Engedélyezve" - -#: src/dialogs.py:445 -#, fuzzy -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Válassz .torrent fájlt" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent fájlok" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Minden fájl" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Külső parancs" - -#: src/common.py:207 -msgid "not found" -msgstr "nem található" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Különböző IP blokklisták letöltése és importálása.\n" -"\n" -"Jelenleg, ez a beépülő a PeerGuardian (bináris és szöveges),\n" -"Safepeer és Emule listákat képes kezelni. A PeerGuardian\n" -"7zip formátum nem kezelt. A fájlokat URL-ként és lokális\n" -"fájlrendszer helyként is meg lehet adni.\n" -"\n" -"A wiki-n található egy oldal, ami blokklista letöltő oldalakra\n" -"mutat:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Text (Tömörítetlen)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP lista (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Text (Zip)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Nem sikerült letölteni az URL-t" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Nem sikerült megnyitni a blokklista fájlt" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Rossz fájltípus vagy hibás blocklist fájl." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importálva" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP-k" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blokklista" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "bejegyzés" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Blokklista URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Töltse le az új feketelistát minden" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "nap" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Blokklista betöltése és teleptése" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importálás" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Befejezett" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr ".ZIP állományok típuskezeléshez szerezze be" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Egy gzip fájlt vártunk, de nem kaptuk meg, vagy valószínűleg sérült a fájl. " -"Kérlek ellenőrizd a Blocklist beállításaid." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Helytelen vezető" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Helyteles varázskód" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Érvénytelen verzió" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Beállíthatod, hogy a torrentet mekkora arányig ossza vissza." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Kívánt arány" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Nincs" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Nincs" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Kívánt arány" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Megmutatja a torrenthez kapcsolódó partnerek ip-jét, országát, kliensét, " -"állapotát és a le-, feltöltési sebességüket.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP cím" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Ügyfél" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Kész (%)" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrent Készítő" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "A torrent erről a fájlról fog készülni" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Fájl:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "A torrent erről a mappáról fog készülni" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Mappa:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Forrás" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Torrentfájl mentés mint:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Torrent betöltése megosztáshoz" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Új torrent hozzáadás a várólistához" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent Fájl" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Tracker" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Web Seedek" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Megjegyzések" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Készítő" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Privát tulajdonság beállítása" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Minél kisebb a darabok mérete, annál hatékonyabb lesz az adatátvitel, de a " -".torrent fájlod nagyobb lesz" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KB\n" -"64 KB\n" -"128 KB\n" -"256 KB\n" -"512 KB\n" -"1024 KB\n" -"2048 KB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Darabok Mérete:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Haladó" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Egy torrent készítő bővítmény" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Új Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Új Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Új Torrent Készítése" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "A fájl mentése mint..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Ki kell választanod a torrent forrását." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Meg kell adnod, hogy hova mentse a torrentet." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Torrent Figyelmeztetések Beállításai" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Eseményhang engedélyezése (szükséges pygame, nem érhető el Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Villogó tálca ikon engedélyezése" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Felugró figyelmeztetések engedélyezése (python-notify -t igényel, Win32 " -"alatt nem működik)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Villogjon a tálca ikon ha egy torrent elkészült vagy felugró üzenet érkezik" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent kész" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Hálózati Erőnlét Mutató bővítmény\n" -"\n" -"Írta: Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Erőnlét: Rendben]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Eseménynapló Beállításai" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Napló fájlok használata" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Napló fájlok" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Partner elutasítva" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blokk letöltve" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Blokk letöltése" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Darab kész" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Tároló eltávolítva" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Tracker figyelmeztetés" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Tracker hiba" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Tracker válasz" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Tracker bejelentés" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Gyors folytatási hiba" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Peer bann hiba" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Hibás hash" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Fájl hiba" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Érvénytelen kérés" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Partner üzenetek" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Elkészült torrent" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Válaszd ki a naplózandó eseményeket" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Eseménynapló" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "üzenet: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Partner üzenet" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip cím: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "kliens: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "darab indexe: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "állapot kód: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Hátralévő idő a sorban " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "blokk indexe: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "partner seb.: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Sebesség beállítása torrentenként." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrent _Letöltési Sebessége" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrent _Feltöltési Sebessége" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrent Feltöltési Sebessége (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Letöltési Sebesség: (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Hálózati Aktivitás Grafikon plugin\n" -"\n" -"Írta Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Grafikon" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Folyamat" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Hiba történt a fájl indítása közben." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Ez a bővítmény megmutatja a torrent fájljait ahol beállíthatod az " -"elsőbbségüket vagy akár azt is, hogy nem akarod letölteni.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Fáljok" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "Torrent _Áthelyezése" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Válaszd ki a mappát ahova át szeretnéd helyezni" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Nem helyezheti át a torrent fájlt egy másik meghajtóra. Kérem ellenőrizze a " -"beállításait. Bővebben: nem helyezti át a letöltött állományokat egy " -"ugyanolyan mappába, ami már létre lett hozva vagy oda át lettek mozgatva a " -"letöltött fájlok mielőtt bármilyen fájl létre nem lesz hozva." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Befejezett letöltések áthelyezése:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Ez a beépülő lehetővé teszi a felhasználóknak, hogy web forrásokat adjanak " -"hozzá a torrentjeikhez." - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Web Seed hozzáadása" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Web Seed hozzáadása" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Letöltési korlát:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Feltöltési korlát:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Aktív torrentek:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Feltöltési slotok:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Kapcsolatok maximuma:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Időzítő beállítások" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"A zöld a felső határ, a sárga az alsó határ, és a piros a megállított." - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "A -1 -re állítot limit végtelennek számít." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUI Config" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Port Szám" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Új Jelszó" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Új Jelszó(megerősítés)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Sablon" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Gomb Stílus" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Minták cache-elése" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Szöveg és kép" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Csak Kép" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "csak szöveget" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Megerősített jelszó <> Új jelszó\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "Lefordít valamit" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Válassz egy url-t vagy egy torrentet, nem mindkettőt." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "nincs adat." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "A frissítésnek nagyobbnak kell lenni, mint 0." - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "darab fájl" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Névjegy" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Torrent hozzáadása" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Alkalmaz" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Automata frissítés:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Beállítás" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug: Adat dump" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Letöltött fájlok törlése" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Tiltás" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Letöltve" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Engedélyez" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Hiba" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Hátralévő idő" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Bejelentkezés" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Kijelentkezés" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Következő frissítés" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Ki" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Érvénytelen jelszó, próbáld újra" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Mindet megállít" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Darabok" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Eggyel lejjebb" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Várólista pozíció" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Eggyel feljebb" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Tracker frissítése" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Oldal frissítése minden:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Torrent törlése" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Az összes folytatása" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Alkalmaz" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Időtúllépés beállítása" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Sebesség" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Indítás" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Elküld" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrent lista" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Teljes méret" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Tracker Státusz" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Torrent feltöltése" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Feltöltve" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "másodperc" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "A Feed automatán letöltődik a frissítési időközöknek megfelelően." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "RSSFeed frissítése kézzel történik" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Kikapcsolva" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Frissítés gyakorisága" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tipus" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Információ" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Minták" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Küldi" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Évad" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Epizód" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Előzmények korlátozása" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Nem egyezik meg" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Év" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Hónap" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "nap" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Kipróbál" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Torrent beillesztése a sor elejére" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Szüneteltet" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Törölje a szűrést, ha megegyezik" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Letöltés" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Csere" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Minta" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Link újraírása" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"A tartalom a Deluge alap mappájába lesz elmentve, vagy egy kérdést fog " -"feltenni, ha nincs beállítva semmi." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge alapbeállítás" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "A tartalom automatikusan le lesz töltve a megadott mappába." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Kiválszt:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Kimenet" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Szűrők" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "FlexRSS mutatása az eszköztáron" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Gomb mutatása az eszköztáron" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Felület" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Több szálas mód (kísérleti)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Tartomány" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Elérési út" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Érték" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Sütik" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Beállítás" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Kereső bővítmények rendezése" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Név:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Új kereső hozzáadásához adja meg a kereső nevét, és az URL-t. Az URL-ben " -"${query} ki lesz cserélve a keresendő kifejezésre.\n" -"Például egy Google keresés így néz ki:\n" -"http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Segítség" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Torrentfájlok keresése névtelenül" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Keresési szöveg" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Válassz Keresőt" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Keresők Rendezése" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Keresés " diff --git a/po/id.po b/po/id.po deleted file mode 100644 index eccdf1005..000000000 --- a/po/id.po +++ /dev/null @@ -1,2391 +0,0 @@ -# Indonesian translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2007-07-03 09:33+0000\n" -"Last-Translator: Gigih Aji Ibrahim \n" -"Language-Team: Indonesian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Tambah Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "HapusTorrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Tunda" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Pengaturan" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugin" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Edit" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Tampilan" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Ukuran" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Kondisi" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Seeder" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Peer" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Sisa Waktu" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Bantuan" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Peer:" - -#: glade/delugegtk.glade:925 -#, fuzzy -msgid "ETA:" -msgstr "ETA:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Ukuran Total:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Status Tracker:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nama:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detil" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Hapus berkas terunduh" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Tampilkan/Sembunyikan" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Tambah Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Tanyai dimana letak menyimpan tiap unduhan" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Lokasi Unduhan" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrent" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Unduh" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Harap Dingat - Perubahan pada seting hanya akan diterapkan saat Deluge " -"dijalankan ulang." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Dari:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Ke:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Port Aktif:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Jaringan" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Aktifkan ikon system tray" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimalkan ke tray ketika ditutup" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Kata Sandi:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge dikunci" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nama" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Unduh" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Unggah" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Pilih direktori unduhan" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Pilih berkas .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Bekas torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Semua berkas" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Alamat IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klien" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Berkas" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Mulai" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/is.po b/po/is.po deleted file mode 100644 index 3915e7757..000000000 --- a/po/is.po +++ /dev/null @@ -1,2388 +0,0 @@ -# Icelandic translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2007-10-26 20:21+0000\n" -"Last-Translator: AxelRafn \n" -"Language-Team: Icelandic \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Skrá" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Niðurhalað:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Upphalað:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Deilendur:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Deili Hlutfall:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Hraði:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Jafningjar:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Áætlaður Tími:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Brot:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "fjöldi skráa:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Heildar Stærð:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Næsta Tilkynning:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nafn:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Slóð:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Upplýsingar" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/it.po b/po/it.po deleted file mode 100644 index 7d1b23b90..000000000 --- a/po/it.po +++ /dev/null @@ -1,2601 +0,0 @@ -# Italian translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-04 18:50+0000\n" -"Last-Translator: Matteo Settenvini \n" -"Language-Team: Italian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Aggiungi torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Aggiungi" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Rimuovi torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Rimuovi" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Libera la lista dai torrent in seeding" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Pulisci" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Avvia o riprendi il trasferimento" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Riprendi" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Metti in pausa il trasferimento" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pausa" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Accoda il torrent in alto" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Su" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Accoda il torrent in basso" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Giù" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Cambia le preferenze di Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Preferenze" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugin" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Archivio" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "A_ggiungi torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Aggiungi _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "Rimuovi completati" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Modifica" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_gin" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Visualizza" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "Barra degli _strumenti" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Dettagli" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Colonne" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Dimensione" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Stato" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Distributori" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Nodi" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Velocità scaricamento" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Velocità invio" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Tempo Rimasto" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Disponibilità" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Rapporto condivisione" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "A_iuto" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Dona per lo sviluppo di Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Dona" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "Sito web" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "Domande _frequenti" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Comunità" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Aiuta a tradurre questa applicazione" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Traduci questa applicazione..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Esegue l'assistente di configurazione iniziale" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Esegui assistente di configurazione" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Scaricati:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Inviati:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Seeder:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Rapporto di condivisione:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Velocità:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Nodi:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Tempo rimanente:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Parti:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Disponibilità:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistiche" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "N° di file:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Dimensione totale:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Stato del tracker:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Prossimo annuncio:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nome:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Percorso:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Informazioni sul torrent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Dettagli" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Rimuovere veramente i torrent selezionati da " -"Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Elimina i file scaricati" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Elimina il file .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Mostra/Nascondi" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Aggiungi un torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Rimuovi completati" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Apri file" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Seleziona tutto" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Deseleziona tutto" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Non scaricare" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normale" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Alta" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Massima" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Unione elenchi tracker" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Il torrent è stato già rilevato in Deluge; unire gli elenchi dei tracker?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Preferenze di Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Chiedere dove salvare ogni scaricamento" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Selezionare una cartella" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Memorizzare tutti i file torrent in:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Memorizzare tutti gli scaricamenti in:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Posizione di scaricamento" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Caricare automaticamente i file torrent in:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Caricamento automatico" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Il numero di torrent attivi eseguiti da Deluge. Impostare a -1 per " -"illimitato." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Numero massimo di torrent attivi simultaneamente:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Abilitare la selezione dei file per i torrent prima di caricare" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Mostrare solo se il torrent contiene più di un file" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Priorità alle parti iniziali e finali dei file nei torrent" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Avviare i torrent nello stato in pausa" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrent" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"L'allocazione completa pre-assegna tutto lo spazio necessario al torrent e " -"previene la frammentazione del disco" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Utilizzare allocazione completa" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "L'allocazione compatta assegna lo spazio solo quando è necessario" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Utilizzare allocazione compatta" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Allocazione" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Scaricamenti" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Attenzione: i cambiamenti a queste impostazioni saranno applicati solo al " -"prossimo riavvio di Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Da:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "A:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge userà automaticamente ogni volta una porta differente" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Porte casuali" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Controlla porta attiva" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Porta attiva:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"La tabella degli hash distribuita può migliorare la quantità di connessioni " -"attive." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Abilita la mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "Tabella distribuita di hash (DHT)" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "Protocollo port mapping NAT" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Scambio di nodi" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Scoperta nodi locali" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Funzioni aggiuntive di rete" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "In arrivo:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Disabilitata\n" -"Abilitata\n" -"Forzata" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "In uscita:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Cerca di crittografare l'intero stream" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Livello:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Handshake\n" -"Intera connessione\n" -"Ambedue" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Crittografia" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Rete" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Accodare i torrent in fondo quando passano in seeding" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Accodare i nuovi torrent sopra a quelli completati" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" -"Fermare il seeding dei torrent quando il rapporto di condivisione diventa:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Pulire automaticamente i torrent che raggiungono il rapporto di condivisione " -"massimo" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Smetti di condividere torrent dopo essere stati in seeding per:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Numero di ore" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Pulisci automaticamente i torrent che raggiungono il tempo di max seed" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Il numero massimo di tentativi di connessione al secondo. Un valore elevato " -"potrebbe mandare in crash alcuni router economici. Impostare -1 per " -"illimitato." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Numero massimo di tentativi di connessione al secondo." - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Il numero totale massimo di slot per l'invio. Impostare a -1 per illimitato." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"La velocità massima di invio per tutti i torrent. Impostare a -1 per " -"illimitata." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"La velocità massima di scaricamento per tutti i torrent. Impostare a -1 per " -"illimitata." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Velocità di scaricamento massima (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" -"Il numero massimo di connessioni permesse. Impostare a -1 per illimitate" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Connessioni massime:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Velocità di invio massima (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Numero massimo di slot di invio:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Il numero massimo di connessioni semi-aperte. Un valore elevato potrebbe " -"mandare in crash alcuni router economici. Impostare a -1 per illimitato." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Numero massimo di connessioni semi-aperte:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Utilizzo di banda globale" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Il numero massimo di slot di invio per torrent. Impostare a -1 per " -"illimitato." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Il numero massimo di connessioni per torrent. Impostare a -1 per illimitato." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Utilizzo di banda per torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Banda" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Influenza in normali nodi bittorrent" - -#: glade/preferences_dialog.glade:1620 -#, fuzzy -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Porta" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Nessuno\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 con autent.\n" -"HTTP\n" -"HTTP con autent." - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Parola d'ordine" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Note utente" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Tipo di proxy" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Proxy per peer" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Proxy per tracker" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Proxy per tracker" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Proxy per DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Proxy per DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Proxy per seed web" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Proxy per seed web" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxy" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Abilitare l'icona nell'area di notifica" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimizzare nell'area di notifica alla chiusura" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Avviare nell'area di notifica" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Area di notifica protetta da password" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Password:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Area di notifica" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Usare la barra di avanzamento avanzata (utilizzo leggermente maggiore di " -"CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Barra avanzamento dettagliata" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge controllerà i server e avvertirà nel caso sia stata rilasciata una " -"nuova versione" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Segnalare i nuovi rilasci" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Aggiornamenti" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Aiutaci a migliorare Deluge inviando le versioni di Python\n" -"e PyGTK, del sistema operativo e il tipo di processore.\n" -"Non saranno inviate altre informazioni." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Informazioni di sistema" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Altro" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Forza ricontrollo" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Ri_prendi" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "Pa_usa" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Rimuovi torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Opzioni tracker" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Aggiorna tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Modifica tracker" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "Richiedi _scrape al tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "A_ccoda" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "In _alto" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Su" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Giù" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "In _fondo" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Apri cartella che lo contiene" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Mostra Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Riprendi tutti" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "Metti tutti in _pausa" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Limite velocità di _scaricamento" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Limite velocità di _invio" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Esci" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Modifica i traker" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Modifica dei tracker" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Selezione file di Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Il torrent non verrà distribuito sulla rete senza tracker (DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Imposta il flag privato" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Configurazione iniziale" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Questo assistente è d'aiuto per configurare Deluge secondo i propri " -"desideri. Se è la prima volta che si usa Deluge, notare che molte delle " -"funzioni di Deluge sono presenti sotto forma di plugin, a cui è possibile " -"accedere facendo clic su Plugin nel menù Modifica o nella barra degli " -"strumenti." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge necessita di un intervallo di porte su cui tenterà di restare in " -"ascolto delle connessioni in arrivo. Le porte predefinite per bittorrent " -"sono 6881~6889; comunque, la maggior parte degli ISP bloccano queste porte, " -"cosicché sarebbe opportuno sceglierne altre, comprese fra 49152 e 65535. In " -"alternativa, è possibile far sì che Deluge scelga delle porte a caso in modo " -"automatico." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Usare porte _casuali" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Effettuare automaticamente lo scaricamento in una posizione predefinita " -"oppure specificare ogni volta tale posizione?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Chiedere dove salvare ciascun file" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Memorizzare tutti gli scaricamenti in: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Selezionare la velocità di upload della propria connessione; tale valore " -"sarà usato per dare automaticamente dei suggerimenti per le impostazioni " -"presenti qui sotto" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Numero massimo di torrent attivi:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8 k\n" -"56 k\n" -"64 k\n" -"96 k\n" -"128 k\n" -"192 k\n" -"256 k\n" -"384 k\n" -"512 k\n" -"640 k\n" -"768 k\n" -"1 Mbit\n" -"2 Mbit\n" -"10 Mbit\n" -"20 Mbit\n" -"40 Mbit\n" -"50 Mbit\n" -"100 Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Velocità di upload della propria connessione:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Aiutaci a migliorare Deluge inviandoci il tuo numero di versione\n" -"di Python e PyGTK, il sistema operativo e il tipo di processore.\n" -"Nessun'altra informazione verrà inviata." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Impossibile avviare il browser. Assicurarsi di aver installato \"python-" -"gnome2-extras\" oppure provare a impostare le proprie variabili ambientali " -"LD_LIBRARY_PATH e MOZILLA_FIVE_HOME a /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Nessun limite" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Attivato" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Altro..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Velocità di scaricamento (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Velocità di invio (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge è bloccato" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge è protetto da password.\n" -"Per mostrare la finestra di Deluge, inserire la propria password" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infinito" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Sconosciuto" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nome" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Tempo rimanente" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Dispon." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Rapporto" - -#: src/interface.py:760 -#, fuzzy -msgid "Choose a directory to switch torrent source to" -msgstr "Scegliere una directory per cambiare il sorgente del torrent a" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Cancellare i vecchi torrent?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "In pausa %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Accodato %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"È disponibile una nuova versione di Deluge. Prelevarla direttamente dal sito?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Connessioni" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Scaricamento" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Invio" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge - Client bittorrent" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Scegliere una directory di scaricamento" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Si è verificato un errore durante il tentativo di aggiungere il torrent. È " -"possibile che il file .torrent sia danneggiato." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Errore torrent duplicato sconosciuto." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Non c'è sufficiente spazio disco libero per completare lo scaricamento." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Spazio richiesto:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Spazio disponibile:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Aggiungi torrent da URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Inserire l'URL del file .torrent da scaricare" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Avvertimento: tutti i file scaricati per questo torrent saranno eliminati!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Rimuovere veramete tutti i torrent in seeding?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "In coda" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Verifica" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Connessione" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Scaricamento metadati" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Scaricamento" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Completato" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Assegnazione" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "byte necessari" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" -"Non è disponibile su disco spazio libero sufficiente per completare lo " -"scaricamento." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Annuncio inviato" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Annuncio OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Allarme" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "codice HTTP" - -#: src/core.py:776 -msgid "times in a row" -msgstr "occorrenze in una riga" - -#: src/core.py:788 -msgid "Warning" -msgstr "Attenzione" - -#: src/files.py:77 -msgid "Filename" -msgstr "Nome file" - -#: src/files.py:82 -msgid "Priority" -msgstr "Priorità" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"La priorità sui file può essere impostata solo quando si usa l'allocazione " -"completa.\n" -"Modificare le preferenze disabilitando l'allocazione compatta, quindi " -"rimuovere e aggiungere nuovamente questo torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Abilitato" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge è software libero, è possibile redistribuirlo e/o\n" -"modificarlo in base ai termini della Licenza Pubblica\n" -"Generale GNU (GNU GPL) come pubblicata dalla\n" -" Free Software Foundation, versione 2 o (a proprio\n" -"piacimento) successiva.\n" -"\n" -"Deluge è distribuito nella speranza che sia utile,\n" -"ma SENZA ALCUNA GARANZIA, comprese anche\n" -"la garanzia implicita di VENDIBILITÀ e di\n" -"ADEGUATEZZA AD UN PARTICOLARE SCOPO.\n" -"Vedere la Licenza Pubblica Generale GNU\n" -"per maggiori dettagli.\n" -"\n" -"Insieme a Deluge dovrebbe essere stata fornita\n" -"anche una copia della Licenza Pubblica Generale GNU.\n" -"In caso contrario la si può richiedere scrivendo a\n" -"'Free Software Foundation, Inc., 51 Franklin Street,\n" -"Fifth Floor, Boston, MA 02110-1301 USA'" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Scegliere un file .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "File torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Tutti i file" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Comando esterno" - -#: src/common.py:207 -msgid "not found" -msgstr "non trovato" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Scarica e importa varie blocklist di IP\n" -"\n" -"Attualmente questo plugin può gestire liste PeerGuardian\n" -"(in formato testo o binario), SafePeer ed Emule.\n" -"file di PeerGuardian in formato 7zip non sono supportati.\n" -"I file possono essere specificati come URL o posizioni\n" -"sul file system locale.\n" -"\n" -"Una pagina con collegamenti ai siti di scaricamento\n" -"delle blocklist è disponibile sul wiki all'indirizzo:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian in formato testo (non compresso)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Elenco IP Emule (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer in formato testo (compresso)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Impossibile scaricare l'URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Impossibile aprire il file della blocklist" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Tipo di file errato o file della blocklist corrotto." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importata" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blocklist" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "voci" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL della blocklist" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Scarica nuove blacklist ogni" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "giorni" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Caricamento e installazione della blocklist" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importazione" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Completo" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Ricevuta eccezione di formato per il file zip:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Era atteso un file di tipo gzip, ma o non è pervenuto un file di tale tipo " -"oppure probabilmente il file è danneggiato. Modificare le proprie preferenze " -"della blocklist." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Leader non valido" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Magic code non valido" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Versione non valida" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Imposta il rapporto desiderato per un torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "Rapporto _desiderato" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Non impostare" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Non impostare" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Rapporto desiderato" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Questo plugin mostra i nodi associati a ogni torrent e il loro IP, nazione, " -"client, percentuale completata e velocità di invio e scaricamento.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Indirizzo IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Client" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Percentuale completata" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Creazione torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Questo torrent verrà creato a partire da un singolo file" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "File:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Questo torrent verrà creato a partire da una directory" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Cartella:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Sorgente" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Salva file torrent come:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Caricare questo torrent in Deluge per il seeding" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Aggiunge il nuovo torrent alla coda" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "File torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Tracker" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Seed web" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Commenti" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autore" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Imposta flag privato" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Minore è la dimensione delle parti, più efficiente sarà il trasferimento, " -"sebbene il file \".torrent\" effettivo risulterà più grande" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Dimensione parti:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Avanzate" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Un plugin per la creazione di torrent" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Nuovo torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Nuovo torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Crea un nuovo torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Salva file come..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "È necessario selezionare una sorgente per il torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "È necessario selezionare un file su cui salvare il torrent." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Preferenze di Notifica torrent" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" -"Abilitare suono per evento (richiede pygame, non disponibile su Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Abilitare il lampeggiamento dell'icona di notifica" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Abilitare popup di notifica (richiede python-notify, non disponibile su " -"Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Completato lo scaricamento del torrent, fa lampeggiare l'icona di notifica " -"e/o mostra un popup" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent completato" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Plugin «Monitor stato della rete»\n" -"\n" -"Scritto da Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Stato: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Preferenze di Registrazione eventi" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Abilitare i file di registro" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "File di registro" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Peer bloccato" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blocco terminato" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Blocco dello scaricamento" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Parte terminata" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Storage spostato" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Avviso del tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Allerta del tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Risposta del tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Annuncio del tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Errore ripristino rapido rifiutato" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Errore peer bandito" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Errore verifica dell'hash fallita" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Errore del file" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Richiesta non valida" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Messaggi dei peer" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent completato" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Selezionare gli eventi da registrare" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Aggiunge una scheda con il registro degli eventi selezionati.\n" -"\n" -"I messaggi d'evento provengono dagli avvisi di libtorrent.\n" -"Se tali messaggi non risultano tradotti nella lingua in uso,\n" -"segnalare questo problema a libtorrent, non a Deluge.\n" -"\n" -"Riguardo ai file di registro, questi sono salvati in una\n" -"directory all'interno della directory di configurazione di Deluge.\n" -"I messaggi d'evento per i singoli torrent sono salvati in file\n" -"di registro individuali chiamati come il file .torrent \n" -"associato. I messaggi d'evento non specifici di alcun\n" -"torrent sono salvati in file di registro chiamati come gli eventi\n" -"(es. peer_messages.log).\n" -"I messaggi d'evento nei file di registro includono anche\n" -"un timestamp.\n" -"L'utente è responsabile della pulizia dei file di registro.\n" -"\n" -"Novità nella versione 0.2\n" -"Gli eventi sono troncati nella visualizzazione. I file di registro no.\n" -"Ora i nuovi eventi vengono mostrati in alto.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Registro degli eventi" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "messaggio d'evento: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Messaggio del peer" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "indirizzo ip: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "client: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "indice delle parti: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "codice di stato: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Occorrenze in una riga: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "indice dei blocchi: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "velocità peer: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Imposta il limite di velocità desiderato per torrent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Velocita _scaricamento torrent" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "_Velocità invio torrent" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Velocità di invio del torrent (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Velocità di scaricamento del torrent (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Plugin «Grafico attività di rete»\n" -"\n" -"Scritto da Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Grafico" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Avanzamento" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Si è verificato un errore durante il tentativo di lanciare il file." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Questo plugin mostra i file contenuti all'interno di un torrent e permette " -"di impostarne la priorità e scegliere quelli che si vuole o non vuole " -"scaricare.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "File" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Questo modulo permette agli utenti di spostare i file di un torrent in " -"un'altra cartella, senza bisogno di rimuovere e aggiungere nuovamente il " -"torrent. Questa funzionalità può essere trovata cliccando col tasto destro " -"del mouse su un torrent.\n" -"Inoltre, permette all'utente di spostare i file correttamente completati in " -"un'altra cartella.\n" -"Nota: I file possono essere spostati unicamente all'interno della stessa " -"partizione" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Sposta torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Scambia sorgente torrent" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Scegliere una directory su cui spostare i file" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Non è possibile spostare il torrent su una partizione diversa. Controllare " -"le proprie preferenze. Inoltre, non è possibile spostare i file di un " -"torrent nella stessa directory che già li contiene oppure spostare i file di " -"un torrent prima che uno di questi sia stato realmente creato." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Spostare gli scaricamenti completati su:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "Questo plugin permette l'aggiunta di seed web ai propri torrent" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Aggiungi seed web" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Aggiungi seed web" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Limite di download:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Limite di upload:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Torrents attivi:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Slot di invio:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Connessioni Massime:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Impostazioni pianificatore" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Verde indica i limiti superiori, giallo i limiti inferiori e rosso indica " -"fermato" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Se un limite è impostato a -1, allora non è applicato alcun limite." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Configura interfaccia Web" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Numero di porta" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nuova password" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Nuova password (conferma)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Modello" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Stile dei pulsanti:" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Cache dei modelli" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Testo e immagine" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Solo immagine" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Solo testo" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Password confermata <> Nuova password\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "traducete qualcosa" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Scegliere un URL oppure un torrent, non entrambi." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "nessun dato." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "refresh deve essere > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "N° di file" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Informazioni" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Aggiungi torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Applica" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Aggiornamento automatico:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Disp" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Configura" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Dump dei dati" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Elimina file scaricati." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Disabilita" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Scaricati" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Abilita" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Errore" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Tempo rimanente" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Login" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Logout" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Prossimo annuncio" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Disattivo" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "La password non è valida, provare ancora" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Tutti in pausa" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Parti" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Sposta in giù nella coda" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Posizione in coda" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Sposta in sù nella coda" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Riannuncia" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Aggiornare la pagina ogni:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Rimuovi torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Riprendi tutti" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Imposta" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Imposta il timeout" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Velocità" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Avvia" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Conferma" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Elenco dei torrent" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Dimensione totale" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Stato del tracker" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Invia torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Inviato" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "URL" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "secondi" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"Il feed verrà recuperato automaticamente, in base all'intervallo di " -"aggiornamento." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Il feed deve essere aggiornato manualmente." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Disabilitato" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Intervallo di aggiornamento" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tipo" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informazioni" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Modelli" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Da" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Stagione" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episodio" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "a" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Restrizione cronologia" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Non coincide" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Anno" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Mese" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Giorno" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Inserire il torrent in cima alla coda." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Impostare lo stato a \"in pausa\"." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Eliminare il filtro quando corrisponde." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Scaricamento" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Sostituzione" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Modello" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Riscrittura collegamento" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"I contenuti verranno salvati nella directory predefinita di Deluge, oppure " -"verrà effettuata una richiesta se non ne è impostata alcuna." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Predefinito di Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" -"Il contenuto verrà scaricato automaticamente nella directory specificata." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Scegliere:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Output" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtri" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Mostrare un'icona FlexRSS nella barra degli strumenti di Deluge." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Mostrare il pulsante sulla barra degli strumenti." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interfaccia" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"I feed saranno recuperati e analizzati in rispettivi thread. L'applicazione " -"non verrà bloccata, ma potrebbe diventare indisponibile." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Threaded (sperimentale)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Recupero feed" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Dominio" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Percorso" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Valore" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookie" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Configurazione" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Gestione plugin di ricerca" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nome:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Aggiungere un nuovo motore di ricerca inserendo un nome e un URL. In Nome, " -"indicare il nome del motore di ricerca. In URL, indicare l'URL della pagina " -"di ricerca. L'interrogazione personalizzata dall' utente sostituirà ogni " -"occorrenza di ${query} nell'URL.\n" -"Ad esempio, una ricerca con Google potrebbe essere:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Aiuto" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Cerca torrent in maniera anonima" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Stringa di ricerca" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Scegliere un motore" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Gestione motori" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Cerca " diff --git a/po/iu.po b/po/iu.po deleted file mode 100644 index 07371bf62..000000000 --- a/po/iu.po +++ /dev/null @@ -1,2389 +0,0 @@ -# Inuktitut translation for deluge -# Copyright (c) 2008 Rosetta Contributors and Canonical Ltd 2008 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2008. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-21 03:11+0000\n" -"Last-Translator: adaminikisi \n" -"Language-Team: Inuktitut \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -#, fuzzy -msgid "Search " -msgstr "search " diff --git a/po/ja.po b/po/ja.po deleted file mode 100644 index 5d1ea6077..000000000 --- a/po/ja.po +++ /dev/null @@ -1,2484 +0,0 @@ -# Japanese translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-22 05:10+0000\n" -"Last-Translator: TAS \n" -"Language-Team: Japanese \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "トレントを追加" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "追加" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "トレントを削除" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "削除" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "シーディングトレントをクリア" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "クリア" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "トレントを開始/再開" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "再開" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "トレントを休止" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "休止" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "トレントのキューを上げる" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "上" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "トレントのキューを下げる" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "下" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Delugeの設定を変更" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "設定" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "プラグイン" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "ファイル(_F)" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "トレントを追加(_A)" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "URLを追加(_U)" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "完了済みをクリア(_C)" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "編集(_E)" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "プラグイン(_g)" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "トレント(_T)" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "表示(_V)" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "ツールバー(_T)" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "詳細(_D)" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "カラム(_C)" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "サイズ" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "状態" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "シーダー" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "ピア" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "下り速度" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "上り速度" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "残り時間" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "可用性" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "共有比" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "ヘルプ(_H)" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Deluge開発者に寄付" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "寄付(_D)" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "ホームページ(_H)" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "FAQ(_F)" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "コミュニティ(_C)" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "このアプリケーションを翻訳する" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "このアプリケーションを翻訳する(_T)..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "初使用時の環境設定ウィザードを実行する" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "環境設定ウィザードの実行(_R)" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "ダウンロード済み:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "アップロード済み:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "シーダー:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "共有比:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "速度:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "ピア:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "残り時間:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "ピース:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "可用性:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "統計" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "ファイル数:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "合計サイズ:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "トラッカー:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "トラッカーの状態:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "次のアナウンス:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "名前:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "パス:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "トレント情報" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "詳細" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "選択したトレントをDelugeから削除しますか?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "ダウンロード済みファイルを削除" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "トレントファイルを削除" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "表示/非表示" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "トレントを追加..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "完了済みをクリア" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "ファイルを開く(_O)" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "全て選択" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "全て選択解除" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "ダウンロードしない" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "標準" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "高" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "最高" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "トラッカーリストをマージする" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "既存トレントの為、トラッカーリストをマージしますか?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Delugeの設定" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "保存先を毎回尋ねる" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "フォルダの選択" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "トレントファイルの保存先:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "保存先を固定:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "保存先" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "トレントファイルの自動読み込み先:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "自動読み込み" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "アクティヴなトレント数(-1は無制限)" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "最大同時アクティヴトレント数:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "トレント読み込み時のファイル選択を有効" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "トレントに1つ以上のファイルが含まれる時のみ表示" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "トレントの最初と最後のピースを優先" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "休止状態でトレントを開始" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "トレント" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "フルアロケーションはトレントに必要なスペースをあらかじめ確保し、ディスクの断片化を防ぎます" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "フルアロケーションを使用" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "コンパクトアロケーションは最低限必要なスペースだけを確保します" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "コンパクトアロケーションを使用" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "アロケーション" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "ダウンロード" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "注意 - 変更した設定は再起動した時に適用されます" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "From:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "To:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "毎回、異なるポートを自動選択" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "ランダムポート" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "使用ポートをテスト" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "使用ポート" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "DHTはアクティブな接続数の改善が見込めるかもしれません" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Mainline DHTを使用" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "ユニバーサルプラグアンドプレイ" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Port Mapping Protocol" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "ピア交換" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Local Peer Discovery" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "ネットワーク詳細" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "インバウンド:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"無効\n" -"有効\n" -"強制" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "アウトバウンド:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "全体の暗号化を優先" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "レベル:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Handshake\n" -"Full Stream\n" -"Either" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "暗号化" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "ネットワーク" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "シーディングする際、トレントのキューを最下部へ移動" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "完了した際、新しいトレントのキューを最上部へ移動" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "設定した共有比に達したらシーディングを停止:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "設定した共有比に達したら自動的にトレントをクリア" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "設定したシード時間に達したらシーディングを停止:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "時間" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "設定したシード時間に達したら自動的にトレントをクリア" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "シーディング" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "シーディング" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "最大接続数(毎秒)。高値はルーターに高負荷なので注意(-1は無制限)" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "最大接続数(毎秒):" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "全トレントの最大上りスロット数(-1は無制限)" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "全トレントの最大上り速度(-1は無制限)" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "全トレントの最大下り速度(-1は無制限)" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "最大下り速度 (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "最大許容接続数(-1は無制限)" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "最大接続数:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "最大上り速度 (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "最大上りスロット数:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "最大半開接続数。高値はルーターに高負荷なので注意(-1は無制限)" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "最大半開接続数:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "全体の帯域幅" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "各トレントの最大上りスロット数(-1は無制限)" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "各トレントの最大接続数(-1は無制限)" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "各トレントの帯域幅" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "帯域幅" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "正式なビットトレントピアに影響" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Password" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Username" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxy type" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "プロキシ" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "システムトレイアイコンを有効" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "閉じたらトレイに最小化" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "最小化で開始" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "トレイ復帰時にパスワードを使用" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "パスワード:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "システムトレイ" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "高度な進歩バーを使用(CPU/RAMを余分に使用)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "進歩バー" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "Delugeは自動的に最新版があるかチェックする事が可能です" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "最新版があれば警告する" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "アップデート" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Delugeの改良を助ける為に、PythonとPyGTKのバージョン、\n" -"OSとプロセッサタイプを開発者へ送ります\n" -"その他の情報は絶対に送りません" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "システム情報" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "その他" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "強制再チェック(_F)" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "再開(_s)" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "休止(_P)" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "トレントを削除(_R)" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "トラッカーオプション(_T)" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "トラッカーをアップデート(_U)" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "トラッカーを編集(_E)" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "キュー(_Q)" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "最上部(_T)" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "上(_U)" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "下(_D)" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "最下部(_B)" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "フォルダを開く(_O)" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "Delugeを表示(_S)" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "全て再開(_R)" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "全て休止(_P)" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "下り速度制限(_D)" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "上り速度制限(_U)" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "終了(_Q)" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "トラッカーを編集" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "トラッカー編集中" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge File Selection" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "トレントはDHTネットワークを使用していません" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "プライベートフラッグをセット" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "First Launch Configuration" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"このウィザードはDelugeをあなた好みに設定する手助けをします。あなたがDelugeを使うのが初めてなら、Delugeの最も大きな特徴であるプラグイン設" -"定に注意を払ってください。プラグインは編集メニューからか、メニューバーの「プラグイン」をクリックする事で設定できます。" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Delugeは接続要求に多くのポートを必要とします。ビットトレントはデフォルトで6881-" -"6889のポートを使用します。しかし多くのISPがそれらのポートをブロックしています。したがって49152-" -"65535のポートを使用する事が推奨されています。Delugeは自動的に49152-65535のポートからランダムに選択する事が可能です。" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "ランダムポートを使用" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "ダウンロードの保存先を固定しますか? それとも毎回指定しますか?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "毎回指定するか尋ねる" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "保存先を指定: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "あなたの回線の上り速度を以下の設定から選んでください。自動的に最適値が設定されます" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "最大アクティヴトレント数:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "回線の上り上限速度:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Delugeの改良を助ける為に、PythonとPyGTKのバージョン、\n" -"OSとプロセッサタイプを開発者へ送ります\n" -"その他の情報は絶対に送りません(_H)" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"ブラウザ状態を取得できません。 python-gnome2-extras がインストールされているか、環境変数 LD_LIBRARY_PATH と " -"MOZILLA_FIVE_HOME を /usr/lib/firefox に設定してみてください。" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "無制限" - -#: src/interface.py:325 -msgid "Activated" -msgstr "活性化" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "その他..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "下り速度 (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "上り速度 (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Delugeはロックされています" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Delugeはパスワードによってロックされています\n" -"Delugeを表示したいなら、パスワードを入力して下さい" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "無限大" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "不明" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "名前" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "残り時間" - -#: src/interface.py:651 -msgid "Avail." -msgstr "可用性" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "共有比" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "休止 %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "キュー済み %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "最新版のDelugeがあります。ウェブサイトからダウンロードしますか?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "接続数" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "ダウンロード" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "アップロード" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent Client" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "保存先を選択" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "トレントを追加中にエラーが発生しました。トレントファイルが壊れているかもしれません" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "不明な複製トレントエラーです" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "ダウンロードに必要なスペースが不足しています" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "必要なスペース:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "利用可能なスペース:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "URLからトレントを追加" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "トレントファイルのURLを入力" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "警戒 - このトレントの全てのダウンロードファイルは削除されます!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "シーディングしている全てのトレントを削除しますか?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "キュー済み" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "チェック中" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "接続中" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "メタデータをダウンロード中" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "ダウンロード中" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "完了済み" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "確保中" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "必要なバイト数" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "ダウンロードに必要な空きスペースがありません" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "アナウンスしました" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "アナウンスOK" - -#: src/core.py:774 -msgid "Alert" -msgstr "警告" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP code" - -#: src/core.py:776 -msgid "times in a row" -msgstr "連続回数" - -#: src/core.py:788 -msgid "Warning" -msgstr "警戒" - -#: src/files.py:77 -msgid "Filename" -msgstr "ファイル名" - -#: src/files.py:82 -msgid "Priority" -msgstr "優先度" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"ファイル優先度はフルアロケーションを使用する場合だけ設定可能です\n" -"コンパクトアロケーションが無効である事を確認して下さい。その際、このトレントを削除、または再度追加して下さい" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "プラグイン" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "有効" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "トレントファイルを選択" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "トレントファイル" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "全てのファイル" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "外部コマンド" - -#: src/common.py:207 -msgid "not found" -msgstr "見つかりません" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"様々なIPブロックリストのダウンロードとインポート\n" -"\n" -"現在、このプラグインはPeerGuardian(バイナリとテキスト)、SafePeer、\n" -"Emule listsを扱うことができます。PeerGuardianの7zip形式ファイルは\n" -"サポートしていません。ファイルはURLかローカルファイルシステム上の\n" -"位置として指定できるかもしれません。\n" -"\n" -"ブロックリストのダウンロードサイトの情報は、以下のウィキで入手可能\n" -"です:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Text (非圧縮)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP list (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Text (Zipped)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "URLをダウンロード出来ません" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "ブロックリストを開けません" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "間違いか壊れているブロックリスト" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "インポート済み" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "ブロックリスト" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "エントリー" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "ブロックリストURL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "新規ブロックリストのダウンロード" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "日毎" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "ブロックリストのロードとインストール" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "インポート中" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "完了" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "ZIPファイルの例外的なフォーマットを検出しました:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "gzipファイルを想定していましたが、得られませんでした。またはファイルが違います。ブロックリスト設定を編集して下さい。" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "無効なリーダー" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "無効なマジックコード" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "無効なバージョン" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "希望する共有比を設定" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "希望共有比(_D)" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "未設定(_N)" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "未設定" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "希望共有比" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"これは各トレントのピアに関連するIP、国、クライアント、進捗率、上り速度、下り速度を表示します。\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IPアドレス" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "クライアント" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "進捗率" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "トレントクリエイター" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "このトレントは1つのファイルで構成されています" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "ファイル:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "このトレントはディレクトリから構成されています" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "フォルダ:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "ソース" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "トレントファイルを保存:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "シーディングする為に、このトレントをDelugeでロード" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "新しいトレントをキューに追加" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "トレントファイル" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "トラッカー" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Webシード" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "コメント" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "作成者" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "プライベートフラッグを設定" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "小さいピースサイズは転送が効率的になりますが、実際のトレントファイルが大きくなるでしょう" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "ピースサイズ:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "詳細" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "トレントクリエイタープラグイン" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "新しいトレント(_N)" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "新しいトレント" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "新しいトレントを作成" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "ファイルに名前を付けて保存..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "トレントのソースを選択しなくてはいけません" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "トレントを保存しなくてはいけません" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "トレント通知選択" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "イベント音を有効(Pygameが必要、Win32では使用不可)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "トレイアイコンの明滅を有効" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "ポップアップ通知を有効(python-notifyが必要。Win32では使用不可)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "トレントのダウンロードが完了した際、トレイアイコンを明滅/ポップアップ通知する" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "トレント完了" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[健康度: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "イベントログ選択" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "ログファイルを有効" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "ログファイル" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "ピアブロック" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "ブロック完了" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "ダウンロードブロック" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "ピース完了" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "ストレージ移動" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "トラッカー警戒" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "トラッカー警告" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "トラッカー応答" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "トラッカーアナウンス" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "ファストレジュームエラー" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "ピア禁止エラー" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "ハッシュ失敗エラー" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "ファイルエラー" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "無効なリクエスト" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "ピアメッセージ" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "トレント完了" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "イベントログを選択" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "イベントログ" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "イベントメッセージ: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "トレント: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "ピアメッセージ" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "IPアドレス: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "クライアント: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "ピースインデックス: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "ステイタスコード: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "連続回数: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "ブロックインデックス: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "ピア速度: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "各トレントの希望速度制限を設定" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "トレント下り速度(_D)" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "トレント上り速度(_S)" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "トレント上り速度(KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "トレント下り速度(KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "グラフ" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "進捗" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "ファイル実行時にエラーが発生しました" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"このプラグインはトレントファイルの中身を表示し、ダウンロードする優先順位やダウンロードしないファイルを決めることができます。\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "ファイル" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "トレントを移動(_M)" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "トレントソースを切り替え(_S)" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "ファイルの移動先ディレクトリを選択" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"トレントを異なるパーティションへ移動させる事が出来ません。設定を確認して下さい。また、既に保存されている為、同じディレクトリへ移動させる事ができません。あ" -"るいは、いずれかのファイルが実際に作成される前にトレントファイルを移動させて下さい" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "完了したダウンロードの移動先:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "このプラグインはトレントをWebシードに追加するのを許容します" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "Webシードに追加(_A)" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Webシードに追加" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "最大下り速度:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "最大上り速度:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "有効トレント数" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "上りスロット数:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "最大接続数:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "スケジューラー設定" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "緑は上限速度、黄色は下限速度、赤は停止" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "-1は無制限" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "ウェブUIコンフィグ" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "ポート番号" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "新しいパスワード" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "新しいパスワード(確認)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "テンプレート" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "ボタンスタイル" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "キャッシュテンプレート" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "テキストと画像" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "画像のみ" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "テキストのみ" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "確認されたパスワード <> 新しいパスワード\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "トレントかURLを片方のみ選択" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "ノーデータ" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "ファイル数" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "アバウト" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "トレントを追加" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "適用" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "オートリフレッシュ:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "可用性" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "コンフィグ" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "デバッグ:データダンプ" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "ダウンロード済みファイルを削除" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "無効" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "ダウンロード済み" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "有効" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "エラー" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "残り時間" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "ログイン" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "ログアウト" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "次のアナウンス" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "オフ" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "無効なパスワードです。もう一度試してください" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "全て休止" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "ピース" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "キューを下げる" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "キューの位置" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "キューを上げる" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "再アナウンス" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "毎回ページリフレッシュする:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "トレントを削除" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "全て再開" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "設定" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "タイムアウトを設定" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "速度" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "開始" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "送信" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "トレントリスト" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "合計サイズ" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "トラッカー" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "トラッカーステイタス" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "トレントをアップロード" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "アップロード済み" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "URL" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "秒" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "フィードはアップデート間隔に基づいて自動的に検索されます" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "フィードを手動でリフレッシュして下さい" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "無効" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "アップデート間隔" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "フィード" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "タイプ" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "フィード" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "情報" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "パターン" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "From" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "シーズン" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "エピソード" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "徹底的" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "履歴制限" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "マッチしません" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "年" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "月" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "日" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "テスト" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "トレントをキューの最上部へ挿入" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "休止状態に設定" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "適合した場合、フィルターを削除" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "ダウンロード" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "置換" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "パターン" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Link Rewriting" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "コンテンツはDelugeのデフォルトディレクトリに保存されます。または無設定の場合、プロンプトが出現します。" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge default" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "コンテンツは指定されたディレクトリに自動的にダウンロードされます" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "選択:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "出力" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "フィルター" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "ツールバーにFlexRSSアイコンを表示" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "ボタンをツールバーに表示" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "インタフェース" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "フィードは自らのスレッドを構文解析して訂正します。アプリケーションは妨げられません。しかし、あまり当てになりません。" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Threaded (実験的)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Feed Retrieval" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "ドメイン" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "パス" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "値" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "クッキー" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "設定" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "検索プラグインの管理" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "名前:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"名前とURLを入力して新しいサーチエンジンを追加します。名前にはサーチエンジン名、URLには検索ページを入力してください。ユーザーの検索クエリーはURLの" -"中では ${query} となります。\n" -"例として、Googleだと以下の通り:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "ヘルプ" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "匿名のトレントを検索" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "文字列検索" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "エンジン選択" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "エンジン管理" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "検索 " diff --git a/po/ka.po b/po/ka.po deleted file mode 100644 index 4864db8d8..000000000 --- a/po/ka.po +++ /dev/null @@ -1,2501 +0,0 @@ -# Georgian translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-19 05:53+0000\n" -"Last-Translator: David Machakhelidze \n" -"Language-Team: Georgian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "ტორენტის დამატება" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "დამატება" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "ტორენტის ამოღება" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "ამოღება" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "თესვადი ტორენტების გაწმენდა" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "გაწმენდა" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "ტორენტის გაშვება ან გაგრძელება" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "გაგრძელება" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "ტორენტის პაუზა" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "პაუზა" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "ტორენტის რიგში მაღლა ატანა" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "ზევით" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "ტორენტის რიგში დაბლა ჩამოტანა" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "დაბლა" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "დელუჯის პარამეტრების ცვლილება" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "პარამეტრები" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "მოდულები" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_ფაილი" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "ტორენტის დამატება" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "ბმულის დამატება" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "დასრულებულების გასუფთავება" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "რ_ედაქტირება" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "მოდულები" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "ტორენტი" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_ხედი" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "ხელსაწყოთა _პანელი" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_დეტალები" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_კოლონები" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "ზომა" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "სტატუსი" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "მთესველები" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "პირები" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "ჩამოტვირთვის სიჩქარე" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "ატვირთვის სიჩქარე" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "დარჩენილი დრო" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "ხელმისაწვდომობა" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "ზიარი რეიტინგი" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "დახმარება" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_თავფურცელი" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_ხდკ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_საზოგადოება" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "დახმარება პროგრამის თარგმნაში" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "თარგმნე ეს პროგრამა" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "უშვებს პირველადი კონფიგურაციის ოსტატი" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "კონფიგურაციის ოსტატის გაშვება" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "ჩამოტვირთულია:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "ატვირთულია:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "მთესველები:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "საზიარო რეიტინგი:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "სიჩქარე:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "პირები:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "ETA:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "ნაჭერი:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "ხელმისაწვდომობა:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "სტატისტიკა" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# ფაილებიდან:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "სრული ზომა:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "მეთვალყურე:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "მეთვალყურის სტატუსი:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "შემდეგი ანონსი:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "სახელი:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "გეზი:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "ინფორმაცია ტორენტზე" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "დეტალები" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"დარწმუნებული ხართ რომ გინდათ ამოიღოთ შემდეგი " -"ტორენტი(ები) დელუჯიდან?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "წაშალე ჩამოტვირთული ფაილები" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "წაშალე .torrent ფაილი" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "ჩვენება/დამალვა" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "ტორენტის დამატება..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "დასრულებულების გასუფთავება" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_ფაილის გახსნა" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "ყველას მონიშვნა" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "მონიშვნის გაუქმება" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "არ ჩამოტვირთო" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "ნორმალური" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "მაღალი" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "უმაღლესი" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "დელუჯის მეთვალყურეთა სიის გაერთიანება" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "ტორენტი უკვე არის დელუჯში, გსურთ მეთვალყრეთა სიის გაერთიანება?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "დელუჯის პარამეტრები" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "შემეკითხე შესანახი ადგილი ყოველი ჩამოტვირთვისას" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "საქაღალდის ამორჩევა" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "შეინახე ყველა ტორენტ ფაილი:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "შეინახე ყველა ჩამოტვირთვა:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "ჩამოტვირთული ფაილების მდებარეობა" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "ავრომატურად ჩატვირთე ტორენტ ფაილები:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "ავტომატური ჩატვირთვა" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "აქტიური ტორენტების რაოდენობა. მიუთითეთ -1 ლიმიტის მოსახსნელად." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "ერთდროულად აქტიური ტორენტების მაქსიმალური რაოდენობა:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "ჩართე ჩამოტვირთვამდე ფაილების შერჩევა ტორენტებისათვის" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "აჩვენე მაშინ მხოლოდ, როცა ტორენტს აქვს ერთზე მეტი ფაილი" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "პირველი და ბოლო ნაჭრების პრიორიზება ტორენტში" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "ტორენტის პაუზით დაწყება" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "ტორენტები" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"სრული ლოკაცია წინასწარ მონიშნავს სივრცეს, რომელიც საჭიროა ტორენტისაგან და " -"ამით გამორიცხავს ფრაგმენტაციას" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "სრული განთავსების ათვისება" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "სივრცის კომპაქტური თვისება მხოლოდ საჭიროების მიხედვით" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "კომპაქტური განთავსების გამოყენება" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "განთავსება" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "ჩამოტვირთვები" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"გაითვალისწინეთ რომ - პარამეტრების აღნიშნული ცვლილებები ძალაში შევა მხოლოდ " -"დელუჯის გადატვირთვის შემდეგ." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "საიდან:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "სად:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "დელუჯი ავტომატურად შეარჩევს განსხვავებულ პორტს ყოველ ჯერზე." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "შემთხვევითი პორტები" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "აქტიური პორტის ტესტირება" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "აქტიური პორტი:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "დისტრიბუციული ჰეშ ცხრილი ხელს უწყობს აქტიურ შეერთებებს" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "მეინლაინ DHT ჩართვა" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT პორტების მინიჭების პროტოკოლი" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "პირების გაცვლა–გამოცვლა" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "ლოკალური პრირების გამოვკვლევა" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "ქსელური დანამატები" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "შემომავალი:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"გამორთული\n" -"ჩართული\n" -"ფორსირებული" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "გამავალი:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "არჩიე დინების სრულად დაშიფრვა" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "დონე:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"ხელის ჩამორთმევა\n" -"სრული დინება\n" -"სხვა" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "დაშიფრვა" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "ქსელი" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "ტორენტების ქვედა რიგში გადატანა მათი დათესვისას" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "ახალი ტორენტების დასრულებულთა ზევით მოთავსება" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "შეაჩერე ტორენტების თესვა როცა მათი ზიარი რეიტინგი მიაღწევს:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"ავტომატურად გაასუფთავე ტორენტები რომლებიც მიაღწევენ მაქსიმალურ ზიარ რეიტინგს" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "თესვა" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "თესვა" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"შეერთების მცდელობების რაოდენობა ერთ წამში. მაღალმა მნიშვნელობამ შეიძლება " -"გაჭედოს იაფ ფასიანი როუტერები. დააყენეთ -1 ლიმიტის მოსახსნელად." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "შეერთების მცდელობების რაოდენობა ერთ წამში:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"ატვირთვის მაქსიმალური სლოტების რაოდენობა. მიუთითეთ –1 ლიმიტოს მოსახსნელად." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"მაქსიმალური ატვირთვის სიჩქარე ყველა ტორენტისათვის. მიუთითეთ –1 ლიმიტის " -"მოსახსნელად." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"ყველა ტორენტის ჩამოტვირთვის მაქსიმალური სიჩქარე. დააყენეთ–1 ლიმიტის " -"მოსახსნელად." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "ჩამოტვირთვის მაქსიმალური სიჩქარე(KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "შეერთებათა მაქსიმალური რაოდენობა. დააყენეთ–1 ლიმიტის მოსახსნელად." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "მაქსიმალური შეერთებები:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "ატვირთვის მაქსიმალური სიჩქარე(KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "ატვირთვის მაქსიმალური სლოტები" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"მაქსიმალური ნახევრად ღია შეერთებები. მაღალ მნიშვნელობას შეუძლია გაჭედოს " -"ზოგიეთი იაფფასიანი როუტერი. დააყენეთ – 1 ლიმიტის მოსახსნელად." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "მაქსიმალური ნახევრად ღია შეერთებები:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "გამტარუანრიანობის გლობალური გამოყენება" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"მაქსიმალური ატვირთვის სლოტები ტორენტზე. დააყენეთ – 1 ლიმიტის მოსახსნელად." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"მაქსიმალური შეერთებების რაოდენობა ტორენტზე. მიუთითეთ –1 ლიმიტოს მოსახსნელად." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "გამტარუნარიანობის გამოყენება ტორენტზე" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "გამტარუნარიანობა" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "გავლენას იქონიებს ბიტტორენტის პირებზე" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "პირების პროქსი" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "პორტი" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "სერვერი" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"არცერთი\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "პაროლი" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "მომხმარებელი" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "პროქსის ტიპი" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "პრირის პროქსი" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "მეთვალყურის პროქსი" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "მეთვალყურის პროქსი" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT პროქსი" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT პროქსი" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "ვებ მთესველის პროქსი" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "ვებ თესვის პროქსი" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "პროქსი სერვერები" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "სისტემური პანელის ხატულა" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "მინიმიზაცია სისტემურ პანელში დახურვისას" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "გაშვება სისტემურ პანელში" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "სისტემური პანელის პაროლით დაცვა" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "პაროლი" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "სისტემური პანელი" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "დეტალური პროგრესის პანელი (იყენებს მეტ პროცესორს/მეხსიერებას)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "დეტალური პროგრესის პანელი" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"დელუჯი შეამოწმებს ჩვენს სერვერებს და შეგატყობინებთ ახალი ვერსიის გამოსვლის " -"შესახებ" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "შეტყობინება ახალი ვერსის გამოსვლისას" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "განახლებები" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"დაგვეხმარეთ დელუჯის განვითარებაში თქვენი Python და PyGTK\n" -"ვერსიების შესახებ ინფორმირებით, ასევე ოპერაციული სისტემისა და პროცესორის " -"შესახებაც.\n" -"არანაირი სხვა სახის ინფორმაცია არ გაიგზავნება." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "ინფორმაცია სისტემის შესახებ" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "სხვა" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_გადამოწმების ფორსირება" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "გაგრძელება" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_პაუზა" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "ტორენტის ამოღება" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_მეთვალყურის პარამეტრები" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "მეთვალყურის განახლება" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "მეთვალყურეთა რედაქტირება" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "მეთვალყურის გაკაწრვა" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "რიგი" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "თავი" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "მაღლა" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "დაბლა" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "ბოლო" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "გახსენი შემცველი საქაღალდე" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "აჩვენე დელუჯი" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "განაგრძე ყველა" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "სრული პაუზა" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "ჩამოტვირთვის სიჩქარის ლიმიტი" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "ატვირთვის სიჩქარის ლიმიტი" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "გასვლა" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "მათვალყრეთა რედაქტირება" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "მეთვალყურეთა რედაქტორი" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "დელუჯის ფაილის შერჩევა" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "ტორენტის დისტრიბუცია მოხდება მეთვალყურის გარეშე DHT ქსელში" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "პირადად მონიშვნის დაყენება" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "კონფიგურაცია პირველი გაშვებისას" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"ეს ოსტატი დაგეხმარებათ მოაწყოთ დელუჯი თქვენი მოთხოვნების შესაბამისად. თუ " -"ახალი მომხმარებელი ხართ გაითვალისწინეთ რომ დელუჯის ფუნქციონალობა " -"დამოკიდებულია მოდულებზე, რომლთა გამოყენებაც შეიძლება ინსტრუმენტების პანელის " -"რედაქტირების მენიუდან." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"დელუჯს სჭირდება პორტების დიაპაზონი, რომელზეც მოისმინება შემომავალი " -"შეერთებები. სტანდარტული პორტები ბიტტორენტისათვის არის 6881-6889, თანაც " -"პროვაიდერების მნიშვნელოვანი ნაწილი აბლოკირებს ამ პორტებს, საჭირო ხდება სხვა " -"პორტების შერჩევა 49152 სა და 65535 შორის. ასევე შესაძლებელია დელუჯმა თვითონ " -"შეარჩიოს სხვა და სხვა პორტები ავტომატურად." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "გამოიყენე სხვა და სხვა პორტები" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"გსურთ რომ დელუჯმა ავტომატურად ჩამოტვირთოს წინასწარ განსაზღვრულ ადგილას, თუ " -"გინდათ, რომ ხელოვნურად მიუთითოთ ყოველი ჩამოტვირთვისას." - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "შემეკითხე თითოეული ფაილისათვის" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "შეინახე ყველა ჩამოტვირთვა: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"შეარჩიეთ ატვირთვის სიჩქარე თქვენი შეერთებისათვის, რომელიც გამოიყენება " -"შემდგომი პარამეტრების ავტომატური კონფიგურაციისათვის." - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "აქტიური ტორენტების მაქსიმალური რაოდ." - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8კ\n" -"56კ\n" -"64კ\n" -"96კ\n" -"128კ\n" -"192კ\n" -"256კ\n" -"384კ\n" -"512კ\n" -"640კ\n" -"768კ\n" -"1მბიტი\n" -"2მბიტი\n" -"10მბიტი\n" -"20მბიტი\n" -"40მბიტი\n" -"50მბიტი\n" -"100მბიტი" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "ატვირთვის ხაზის სიჩქარე:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"დაგვეხმარეთ დელუჯის განვითარებაში და გამოგვიგზავნეთ Python და PyGTK\n" -"ვერსიები, ოპ. სისტემისა და პროცესორის ტიპები. \n" -"არანაირი სხვა ინფორმაცია არგაიგზავნება." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "ლიმიტის გარეშე" - -#: src/interface.py:325 -msgid "Activated" -msgstr "აქტიურია" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "სხვა..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "ჩამოტვირთვის შესახებ" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "ატვირთვის სიჩქარე (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "დელუჯი ბლოკირებულია" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"დელუჯი დაცულია პაროლით.\n" -"დელუჯის განჯრის გამოსახვისთვის აკიფეთ თქვენი პაროლი" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "უსასრულო" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "უცნობია" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" -"_: instable.src#DLG_INSERT_TABLE.FT_NAME.fixedtext.text\n" -"სახელი" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "ხელმისაწ." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "რატიო" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "პაუზა %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"გამოსულია დელუჯის ახალი ვერსია. გსურთ გადახვიდეთ ჩამოტვირთვის საიტზე?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "შეერთებები" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "დელუჯი" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "ჩამოტვირთვა" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "ატვირთვა" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "დელუჯი ბიტტირენტ კლიენტი" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "შეარჩიეთ ჩამოსატვირთი დასტა" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"შეცდომა ტორენტის დამატებისას. შესაძლოა თქვენი .torrent ფაილი დაზიანებულია." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "უცნობი დუბლიკატი ტორენტის შეცდომა" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "საჭირო სივრცე:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "დარჩენილი ადგილი" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "ტორენტის URL-დან დამატება" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "შეიყვანეთ ჩამოსატვირთი .torrent-ის URL" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "გაფრთხილება - წაიშლება ყველა ჩამოტვირთული ფაილი ამ ტორენტისათვის." - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "ნამდვილად გსურთ ყველა თესვადი ტორენტის ამოღება?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "რიგშია" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "შემოწმება" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "შეერთება" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "მეტა-ინფორმაციის ჩამოტვირთვა" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "ჩამოტვირთვა" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "დასრულდა" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "განთავსება" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "საჭირო ბაიტები" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "ანონსი გაიგზავნა" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "ანონსი OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "გაფრთხილება" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP კოდი" - -#: src/core.py:776 -msgid "times in a row" -msgstr "დროები სრტრიქონებში" - -#: src/core.py:788 -msgid "Warning" -msgstr "ყურადღება" - -#: src/files.py:77 -msgid "Filename" -msgstr "ფაილის სახელი" - -#: src/files.py:82 -msgid "Priority" -msgstr "პრიორიტეტი" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"ფაილების პრიორიტეტის მითითება შეიძლება მხოლოდ სრული ლოკაციის გამოყენებისას.\n" -"შეცვალეთ პარამეტრები და გამორთეთ კომპაქტური ლოკაცია, შემდეგ ამოაგდეთ და " -"ხელახლა გახსენით ეს ტორენტი." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "მოდული" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "ჩართულია" - -#: src/dialogs.py:445 -#, fuzzy -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "შეარჩიე .torrent ფაილი" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "ტორენტ ფაილები" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "ყველა ფაილი" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "გარე ბრძანება" - -#: src/common.py:207 -msgid "not found" -msgstr "ვერ ვიპოვე" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip ფორმატში)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Text (შეკუმშვის გარეშე)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP სია (GZip ფორმატში)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer ტექსტი (Zip ფორმატში)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "ვერ ვტვირთავ URL-დან" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "ვერ გავხსენი ბლოკირების სიის ფაილი" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "იმპორტირებული" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP-ები" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "ბლოკირების სია" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "ელემენტები" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "ბლოკირების სიის URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "ბლოკირების სიის ჩამოტვირთვა და ინსტალაცია" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "იმპორიტება" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "შესრულებულია" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"მოსალოდნელი იყო gzip ფაილი, მაგრამ ვერ მივიღეთ ან ფაილი დაზიანდა. შეასწორეთ " -"ბლოკირების სიის პარამეტრები" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "არასწორი ლიდერი" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "არასწორი მაგიური კოდი" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "არასწორი ვერსია" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "მიუთითეთ სასურველი რეიტინგი ტორენტისათვის." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "განსაზღვრული შეფარდება" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "არ არის მითითებული" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "არ არის მითითებული" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "სასურველი რეიტინგი" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP მისამართი" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "კლიენტი" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "პროცენტი დასრულდა" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "ტორენტის შემქმნელი" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "ეს ტორენტი შეიქმნება ერთი ფაილისაგან" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "ფაილი:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "ეს ტორენტი შეიქმნება დასტისაგან" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "დასტა:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "წყარო" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "შეინახე ტორენტ ფაილი როგორც:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "ჩატვირთე ეს ტორენტი დელუჯში თესვისათვის" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "ახალიტ რტორენტის რიგში ჩამატება" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "ტორენტ ფაილი" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "მეთვალყურეები" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "კომენტარები" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "ავტორი" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -#, fuzzy -msgid "Set Private Flag" -msgstr "პრივატულად მონიშვნა" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "ანჭრის ზომა:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "დამატებით" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "ტორენტის შემქმნელი მოდული" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "ახლი ტორენტი" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "ახალი ტორენტი" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "ახალი ტორენტის შექმნა" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "ფაილის შენახვა როგორც..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "თქვენ უნდა შეარჩიოთ წყარო ტორენტისათვის" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "თქვენ უნდა შეარჩიოთ ფაილი ტორენტის შესანახად." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "ტორენტის შეტყობინებების პარამეტრები" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" -"ჩართე გახმოვანება (საჭიროებს პაკეტს: pygame, არ არის Win32 პლატფორმისათვის)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "მოციმციმე სისტემური ხატულის ჩართვა" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"ჩართე მცურავი შეტყობინებები (საჭიროების python-notify, არ არის Win32 " -"პლატფორმისათვის" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "ტორენტი დასრულდა" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"ქსელის მონიტორინგის მეოდული\n" -"ავტორი: Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -#, fuzzy -msgid "[Health: OK]" -msgstr "[Health: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -#, fuzzy -msgid "Event Logging Preferences" -msgstr "ივენთების ჟურნალის პარამეტრები" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "ჩართე ჟურნალის ფაილები" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "ჟურნალის ფაილები" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "პირი ბლოკირებულია" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "ბლოკირება დასრულდა" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "ბლოკირების ჩამოტვირთვა" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "ნაჭერი დასრულდა" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "მეთვალყურის გაფრთხილება" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "მეთვალყურის შეტყობინება" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "მეთვალყურის პასუხი" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "მეთვალყურის ანონსი" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "პირის ბლოკირების შეცდომა" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "ჰეშის შეცდომა" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "ფაილის შეცდომა" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "არასწორი მოთხოვნა" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "პირის შეტყობინებები" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "ტორენტი დასრულდა" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "შეარჩიეთ ივენთები ჟურნალიზებისთვის" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "ივენთების ჟურნალი" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "ივენთის შეტყობინება: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "ტორენტი: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "პირის შეტყობინება" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip მისამართი: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "კლიენტი: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "ნაჭრის ინდექსი: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "სტატუსის კოდი: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "რამდენჯერ სტრიქონში: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "ბლოკის ინდექსი: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "პირის სიჩქარე: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "დააყენეთ განსაზღვრული სიჩქარის ლიმიტი ყოველ ტორენტზე" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "ტორენტის ჩამოტვირთვის სიჩქარე" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "ტორენტის ატვირთვის სიჩქარე" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "ტორენტის ატვირთვის სიჩქარე (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "ტორენტის ჩამოტვირთვის სიჩქარე (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"ქსელის აქტივობის გრაფიკის მოდული\n" -"ავტორი: Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "გრაფიკი" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "პროგრესი" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "შეცდომა ფაილის გაშვებისას." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "ფაილები" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "ტორენტის გადატანა" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "შეარჩიეთ დირექტორია ფაილების გადასატანად" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-გაუქმება" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-დიახ" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "ორგანიზატორის პარამეტრები" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUi კონფიგურაცია" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "პორტის ნომერი" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "ახალი პაროლი" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "ახალი პაროლი(დასტური)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "შაბლონი" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "ღილაკების სტილი" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "შაბლონების ქეშირება" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "ტექსტი და სურათები" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "მხოლოდ სურათები" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "მხოლოდ ტექსტი" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "დადასტურებული პაროლი < > ახალი პაროლი\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "რამის თარგმან" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "არ არის მონაცემები." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# ფალებიდან" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "პროგრამის შესახებ" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "ტორენტის დამატება" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "გააქტიურება" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "ავტომატური განახლება:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Ava" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "კონფიგურაცია" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "ჩამოტვირთული ფაილების წაშლა" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "გამორთვა" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "ჩამოტვირთულია" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "ჩართვა" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "შეცდომა" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Eta" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "შესვლა" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "გამოსვლა" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "შემდეგი ანონსი" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "გამორთვა" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "არასწორი პაროლი, კიდევ სცადეთ" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "ყველას პაუზა" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "ნაჭრები" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "რიგში უკან დაწევა" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "ხელახალი ანონსი" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "გვერდის განახლება ყოველ:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "ყველას გაგრძელება" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "მითითება" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "დროის მითითება" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "სიჩქარე" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "გაგზავნა" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "ტორენტების სია" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "სრული ზომა" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "მეთვალყურე" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "მეთვალყურის სტატუსი" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "ტორენტის ატვირთვა" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "ატვირთულია" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "წამები" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "ლენტა ავტომატურად განახლდება, მითითებული ინტერვალის მიხედვით" - -#: plugins/FlexRSS/FlexRSS.glade:115 -#, fuzzy -msgid "Feed must be refreshed manually." -msgstr "ლენტის განახლება უნდა მოხდეს ხელოვნურად" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "გამორთული" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "განახლების ინტერვალი" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "ლენტები" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "ტიპი" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "ლენტი" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr " ინფორმაცია" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "ნიმუშები" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "საიდან" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "სეზონი" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "ეპიზოდი" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "რის გავლით" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "ისტორიის აკრძალვა" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "არ ემთხვევა" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "წელი" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "თვე" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "დღე" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "ტესტი" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "ტორენტის პირველ რიგში დამატება" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "ჩამოტვირთვა" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "შემცვლელი" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "ნიმუში" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "დელუჯის სტანდარტები" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "შეარჩიეთ:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "გამომავალი" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "ფილტრები" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "აჩვენე ღილაკი პანელზე" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "ინტერფეისი" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "ლენტის მიღება" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "დომენი" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "გეზი" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "მნიშვნელობა" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "კუკიები" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "კონფიგურაცია" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "საძიებო მოდულების მართვა" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "სახელი:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "დახმარება" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "საძიებელი ფრაზა" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "შეარჩიეთ ძრავა" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "ძრავების მართვა" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "ძიება " diff --git a/po/ko.po b/po/ko.po deleted file mode 100644 index 9b2dc6f9a..000000000 --- a/po/ko.po +++ /dev/null @@ -1,2519 +0,0 @@ -# Korean translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-20 01:43+0000\n" -"Last-Translator: k2hyun \n" -"Language-Team: Korean \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#~ msgid "File was not found" -#~ msgstr "파일을 찾을수 없습니다" - -#~ msgid "Download on start" -#~ msgstr "다운로드 시작" - -#~ msgid "Custom:" -#~ msgstr "사용자 선택:" - -#~ msgid "Open folder with:" -#~ msgstr "다음으로 폴더 열기:" - -#~ msgid "" -#~ "Auto-detect (xdg-open)\n" -#~ "Konqueror\n" -#~ "Nautilus\n" -#~ "Thunar" -#~ msgstr "" -#~ "자동인식(xdg-open)\n" -#~ "Konqueror\n" -#~ "노틸러스\n" -#~ "Thunar" - -#~ msgid "Desktop File Manager - only for non-Windows platforms" -#~ msgstr "데스크탑 파일 관리자 - Windows 이외의 플랫폼만 해당" - -#~ msgid "High download limit:" -#~ msgstr "최대 다운로드 제한:" - -#~ msgid "High upload limit:" -#~ msgstr "최대 업로드 제한:" - -#~ msgid "Low download limit:" -#~ msgstr "최소 다운로드 제한:" - -#~ msgid "Low upload limit:" -#~ msgstr "최소 업로드 제한:" - -#~ msgid "Go" -#~ msgstr "이동" - -#~ msgid "Bookmarks" -#~ msgstr "북마크" - -#~ msgid "Show the search bar on the toolbar" -#~ msgstr "도구모음에 검색창 보이기" - -#~ msgid "Search Bar - restart required" -#~ msgstr "검색 창 - 다시 요청" - -#~ msgid "Browser" -#~ msgstr "브라우저" - -#~ msgid "Launch Browser" -#~ msgstr "브라우저 실행" - -#~ msgid "" -#~ "msgidDeluge is password protected.\n" -#~ "To show the Deluge window, please enter your password" -#~ msgstr "" -#~ "msgstrDeluge는 암호로 보호되고 있습니다.\n" -#~ "Deluge 창을 보시려면 암호를 입력해 주세요." - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "토런트 추가" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "추가" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "토런트 제거" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "제거" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "배포중인 토런트 비우기" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "비우기" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "토런트 시작 또는 재시작" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "계속받기" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "토런트 일시정지" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "일시정지" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "토런트 대기 순서 올리기" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "위로" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "토런트 대기 순서 내리기" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "아래로" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Deluge 기본 설정 변경" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "기본 설정" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "플러그인" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "파일(_F)" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "토런트 추가(_A)" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "_URL 추가" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "완료된 것 비우기(_C)" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "편집(_E)" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "플러그인(_G)" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "토런트(_T)" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "보기(_V)" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "도구 모음(_T)" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "상세 정보(_D)" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "열(_C)" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "크기" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "상태" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "배포자" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "피어" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "다운 속도" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "업 속도" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "남은 시간" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "유효성" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "공유 비율" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "도움말(_H)" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Deluge 개발자에게 기부하기" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "기부하기(_D)" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "홈페이지(_H)" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "빈번한 질문들(_F)" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "커뮤니티(_C)" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "이 프로그램 번역 돕기" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "이 프로그램 번역하기(_T)" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "처음 설정 마법사 실행" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "설정 마법사 실행(_R)" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "다운로드 양:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "업로드 양:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "배포자 수:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "공유 비율:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "속도:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "피어 수:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "남은시간:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "조각 개수:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "유효성:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "통계" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "파일 개수:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "전체 크기:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "트래커:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "트래커 상태:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "다음 알림:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "파일 이름:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "경로:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "토런트 정보" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "상세 정보" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "선택한 토런트를 Deluge에서 제거 하시겠습니까?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "다운로드한 파일들 삭제" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr ".torrent 파일 삭제" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "보이기/숨기기" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "토런트 추가..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "완료된 것 비우기" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "파일 열기(_O)" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "모두 선택" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "모두 선택 해제" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "다운로드 제외" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "보통" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "높음" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "가장 높음" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge의 트래커 목록에 병합." - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "Deluge에서 동일한 토런트가 발견되었습니다. 기존의 트래커 목록에 추가하시겠습니까?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge 기본 설정" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "다운로드시 저장할 위치를 물어보기" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "폴더 선택" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "모든 토런트 파일을 여기에 보관:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "모든 다운로드를 이곳에 저장:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "다운로드 위치" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "이곳의 모든 토런트 파일들을 자동으로 불러오기:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "자동으로 불러오기" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "Deluge는 지정한 개수까지만 토런트를 활성화 할 것입니다. 무제한은 -1로 설정." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "최대 동시 활성 토런트 개수:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "토런트를 불러오기 전에 다운로드할 파일을 선택하도록 설정" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "토런트에 두 개 이상의 파일이 포함되었을 때만 사용" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "토런트내 파일들의 처음과 마지막 조각을 더 우선함" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "일시정지 상태로 토런트를 시작" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "토런트 목록" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "전체 할당을 사용하면 토런트에서 필요로 하는 모든 공간을 미리 할당 받습니다. 디스크의 단편화를 최소화 할 수 있습니다." - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "전체 할당 사용 (권장)" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "단순 할당을 사용하면 필요할 때만 공간을 할당 받습니다." - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "단순 할당 사용" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "저장공간 할당 방식" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "다운로드" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "안내 - 이곳에서 변경된 설정 사항들은 Deluge를 재시작해야 적용됩니다." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "범위:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "~" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge가 매번 자동으로 다른 포트를 선택하도록 합니다." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "무작위 포트" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "포트 활성화 검사" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "활성 포트:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "DHT 사용" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "범용 플러그 앤 플레이" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT 포트 맵핑 프로토콜" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "피어 교환" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "로컬에서 피어 찾기" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "기타 네트워크" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "들여오기:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"사용하지 않음\n" -"사용\n" -"강제 사용" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "내보내기:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "선호하는 전체 스트림 암호화 방식" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "수준:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"핸드쉐이크\n" -"스트림 전체\n" -"모두 사용" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "암호화" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "네트워크" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "배포를 시작할 때 토런트를 대기열의 제일 아래쪽으로 옮김" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "새 토런트를 완료된 것들보다 위쪽에 대기시킴" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "공유 비율이 다음에 도달하면 토런트의 배포를 중단:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "최대 공유 비율에 도달하면 자동으로 토런트 비우기" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "배포중" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "배포중" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"초당 연결을 시도할 수 있는 최대 횟수입니다. 높은 값으로 설정하면 몇몇 저급 라우터들은 고장을 일으킬수도 있습니다. 무제한은 -1로 " -"설정." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "초당 최대 연결 시도:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "전체 토런트의 최대 업로드 개수입니다. 무제한은 -1로 설정." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "전체 토런트의 최대 업로드 속도입니다. 무제한은 -1로 설정." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "전체 토런트의 최대 다운로드 속도입니다. 무제한은 -1로 설정." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "최대 다운로드 속도 (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "연결을 허용할 최대 개수입니다. 무제한은 -1로 설정." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "최대 연결 개수:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "최대 업로드 속도 (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "최대 업로드 개수:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "최대 단방향 연결 개수입니다. 높은 값으로 설정하면 몇몇 저급 라우터들은 고장을 일으킬수 있습니다. 무제한은 -1로 설정." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "최대 단방향 연결 개수:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "전체 대역폭 사용량" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "토런트 하나당 최대 업로드 개수입니다. 무제한은 -1로 설정." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "토런트 하나당 연결 가능한 최대 개수입니다. 무제한은 -1로 설정." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "토런트당 대역폭 사용량" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "대역폭" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "피어 프록시" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "포트" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "서버" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"없음\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "암호" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "사용자이름" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "프록시 종류" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "피어 프록시" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "트래커 프록시" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "트래커 프록시" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT 프록시" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT 프록시" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "웹 배포 프록시" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "웹 배포 프록시" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "프록시" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "시스템 알림 영역에 아이콘 표시" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "닫으면 알림 영역으로 최소화" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "알림 영역에서 시작" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "알림 영역에 있을때 암호로 보호" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "암호:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "시스템 알림 영역" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "고급 진행상황 막대를 사용 (CPU와 RAM을 조금 더 사용)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "상세한 진행상황 막대" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "Deluge가 서버를 확인하여 새로운 버전이 발견되면 당신에게 알려줍니다." - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "새 버전이 배포되면 알림" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "업데이트" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Deluge의 개선을 돕기 위해 Python과 pyGTK의 버전, OS와 프로세서의\n" -"종류를 제작자에게 보냅니다. 이외의 정보는 절대로 전송하지 않습니다." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "시스템 정보" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "기타" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "강제 재검사(_F)" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "다시시작(_S)" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "일시정지(_P)" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "토런트 제거(_R)" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "트래커 옵션(_T)" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "트래커 업데이트(_U)" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "트래커 수정(_E)" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "트래커 스크랩(_S)" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "대기열(_Q)" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "제일 위로(_T)" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "위로(_T)" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "아래로(_D)" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "제일 아래로(_B)" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "저장된 폴더 열기(_O)" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "Deluge 보기이(_S)" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "모두 재시작(_R)" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "모두 일시정지(_P)" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "다운로드 속도 제한(_D)" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "업로드 속도 제한(_U)" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "종료(_Q)" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "트래커 수정" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "트래커 수정중" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge 파일 선택" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "트래커가 없는 네트워크(DHT)에서는 토런트가 공유되지 않도록 합니다." - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "비공개 플래그 설정" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "최초 실행시 설정사항" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"마법사가 Deluge의 연결 설정을 도와 드립니다. Deluge를 처음 이용한신다면 Deluge의 다양한 기능과 플러그인의 추가 기능을 " -"잘 살펴 보세요. 편집 메뉴나 도구 모음에서 있는 플러그인을 클릭하면 확인 할 수 있습니다." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge는 들어오는 연결을 청취하기 위해 포트를 필요로 합니다. 비트토런트의 기본 포트 범위는 6881-6889 인데 대부분의 " -"ISP들이 이 포트를 막아두고 있습니다. 때문에 49152에서 65535 사이의 다른 포트를 이용하길 권장합니다. Deluge가 자동으로 " -"무작위로 포트를 선택하도록 할 수 있습니다." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "무작위 포트 사용(_R)" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Deluge가 미리 지정한 위치로 자동적으로 다운로드하길 원하십니까? 아니면 다운로드시 매번 다운로드할 위치를 묻기를 원하십니까?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "각 파일을 어디에 저장할지 묻습니다." - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "기본 다운로드 경로: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "인터넷 회선 속도를 선택하세요. 자동으로 최적의 상태로 맞추어 드립니다." - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "최대 활성 토런트:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "당신의 업로드 회선 속도:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Deluge의 개선을 돕기 위해 Python과 pyGTK의 버전, OS와 프로세서의\n" -"종류를 제작자에게 보냅니다. 이외의 정보는 절대로 전송하지 않습니다.(_H)" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"브라우저 찾을 수 없습니다. python-gnome2-extras가 설치되어 있는지 확인하거나 환경 변수 LD_LIBRARY_PATH와 " -"MOZILLA_FIVE_HOME을 /usr/lib/firefox로 설정 하십시오." - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "무제한" - -#: src/interface.py:325 -msgid "Activated" -msgstr "활성화됨" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "사용자 지정" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "다운로드 속도 (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "업로드 속도 (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge가 잠겨 있습니다." - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge는 암호로 보호되고 있습니다.\n" -"Deluge 창을 보시려면 암호를 입력해주세요." - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "무한대" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "모름" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "이름" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "남은시간" - -#: src/interface.py:651 -msgid "Avail." -msgstr "유효성" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "비율" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "일시정시 %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "대기열 %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "새로운 버전의 Deluge가 있습니다. 다운로드 사이트로 이동하시겠습니까?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "연결 수" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "다운로드" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "업로드" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge 비트토런트 클라이언트" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "다운로드 위치 선택" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "토런트를 추가하는 중에 오류가 발생했습니다. 이 .torrent 파일에 오류가 있을 가능성이 있습니다." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "다운로드를 완료하기에는 저장공간이 부족합니다." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "필요한 공간:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "이용 가능한 공간:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "URL로 토런트 추가" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "다운로드할 .torrent의 URL을 입력" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "경고 - 이 토런트로 다운로드한 모든 파일이 삭제됩니다!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "정말로 배포중인 토런트를 모두 제거 하시겠습니까?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "대기중" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "검사중" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "연결 시도중" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "메타데이터 다운로드중" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "다운로드중" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "완료됨" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "할당중" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes가 필요함" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "다운로드를 완료하기에는 빈 공간이 부족합니다." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "알림 보냄" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "알림 정상" - -#: src/core.py:774 -msgid "Alert" -msgstr "경고" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP 코드" - -#: src/core.py:776 -msgid "times in a row" -msgstr "시도 횟수" - -#: src/core.py:788 -msgid "Warning" -msgstr "경고" - -#: src/files.py:77 -msgid "Filename" -msgstr "파일이름" - -#: src/files.py:82 -msgid "Priority" -msgstr "우선순위" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"파일 우선순위는 전체 할당을 사용중일때만 설정할 수 있습니다.\n" -"기본 설정에서 단순 할당으로 되어있는 설정을 전체 할당으로 변경하신 후 토런트를 제거하고 다시 추가 하십시오." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "플러그인" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "사용" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr ".torrent 파일 선택" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "토런트 파일" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "모든 파일" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "외부 명령어 =" - -#: src/common.py:207 -msgid "not found" -msgstr "찾을 수 없습니다." - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Text (Uncompressed)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP list (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Text (Zipped)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "URL로부터 다운로드 할 수 없습니다." - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "차단목록 파일을 열수 없습니다." - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "가져오기 완료" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "차단목록" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "차단목록 URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "일" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "차단목록을 불러들여 설치" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "가져오는 중" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "완료" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "버전이 올바르지 않습니다." - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "토런트에 희망 비율 설정." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "희망 비율(_D)" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "설정하지 않음(_N)" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "설정하지 않음" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "희망 비율" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP 주소" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "클라이언트" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "완료 비율" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "토런트 생성기" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "파일로부터 토런트를 생성합니다." - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "파일:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "디렉토리로 부터 토런트를 생성합니다." - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "폴더:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "소스" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "토런트를 저장할 위치:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "생성된 토런트를 대기열에 추가" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "토런트 파일" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "트래커" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "웹 배포" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "설명" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "제작자" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "비공개 플래그 설정" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "조각의 크기:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "고급 설정" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "토런트 제작 플러그인" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "새 토런트(_N)" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "새 토런트" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "새 토런트 만들기" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "저장.." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "토런트의 소스를 선택해야 합니다." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "토런트 공지 기본 설정" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "알림 영역의 아이콘를 깜빡거림" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "풍선 알림창 사용 (python-notify를 필요로 하며, Win32에서는 사용할수 없음)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "다운로드가 완료되면 알림 영역의 아이콘을 깜빡이거나 풍선 알림으로 알리도록 합니다." - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "토런트 완료" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"네트워크 상태 점검 플러그인\n" -"\n" -"제작자 Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[네트워크 상태: 정상]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "이벤트 기록 설정" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "로그 파일 사용" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "로그 파일" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "배포가 차단됨" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "차단 완료됨" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "조각이 완성됨" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "저장 위치 옮김" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "트래커 경고" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "트래커 경고" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "트래커 응답" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "트래커 알림" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "피어 차단 오류" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "해시 실패 오류" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "파일 오류" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "잘못된 요청" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "피어 메시지" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "토런트 끝마침" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "이벤트 로그 선택" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "이벤트 기록" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "이벤트 메시지: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "토런트: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "피어 메시지" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip 주소: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "클라이언트: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "조각 인덱스: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "상태 코드: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "시도 횟수: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "차단 인덱스: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "피어 속도: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "토런트 하나당 희망하는 제한 속도 설정." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "토런트 다운로드 속도(_D)" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "토런트 업로드 속도(_S)" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "토런트 업로드 속도 (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "토런트 다운로드 속도(KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"네트워크 활성 그래프 플러그인\n" -"\n" -"제작자 Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "그래프" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "진행 상황" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "파일" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "토런트 옮기기(_M)" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "파일을 옮겨놓을 디렉토리" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"토런트를 다른 파티션으로 옮길 수 없습니다. 설정을 확인하십시오. 또한 작성중인 토런트를 현재 저장된 폴더와 같은 폴더로 저장 또는 옮길 " -"수 없습니다." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "다운로드가 완료되면 다음 위치로 옮김:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "웹 배포 추가(_A)" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "웹 배포 추가" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "스케줄러 설정" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "녹색은 최대 제한, 노랑은 최소 제한, 빨강은 정지." - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "무제한은 -1로 설정." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUI 설정" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "포트 번호" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "새 패스워드" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "새 패스워드(확인)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "버튼 모양" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "글자와 그림" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "그림만" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "글자만" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "현재 패스워드 <> 새 패스워드\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "데이터 없음." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "파일 개수" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "프로그램 정보" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "토런트 추가" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "적용" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "자동 새로고침:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "유효성" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "설정" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:데이터 덤프" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "다운로드한 파일을 삭제:" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "사용 안함" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "다운로드 양" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "사용" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "오류" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "남은시간" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "로그인" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "로그아웃" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "다음 알림" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "꺼짐" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "패스워드가 틀립니다. 다시 입력하세요." - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "모두 일시정지" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "조각들" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "대기열 내리기" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "대기열 위치" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "대기열 올리기" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "다시 알림" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "페이지 새로고침 간격:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "토런트 제거" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "모두 다시시작" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "설정" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "시간초과 설정" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "속도" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "시작" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "전송" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "토런트 목록" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "전체 크기" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "트래커" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "트래커 상태" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "업로드 토런트" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "업로드 양" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "초" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "비활성" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "업데이트 간격" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "피드 목록" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "종류" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "피드" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "정보" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "형식" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "보낸이" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "시즌" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "에피소드" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "일치하지 않습니다." - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "년" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "월" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "일" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "시험" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "일시정지 상태로 설정." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "필터와 일치하면 삭제" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "다운로드" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "재설정" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "패턴" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "링크 다시쓰기" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge 디폴트" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "컨텐츠를 자동으로 지정된 디렉토리로 다운로드 합니다." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "선택:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "출력" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "필터" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Deluge의 도구 모음에 FlexRSS의 아이콘을 표시." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "도구 모음에 버튼을 표시." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "인터페이스" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "피드 검색" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "도메인" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "경로" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "값" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "쿠키 목록" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "구성" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "검색 플러그인 관리" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "이름:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"이름과 URL을 입력하여 새로운 검색 엔진을 추가할 수 있습니다. 이름에는 사용할 검색 엔진의 이름을 입력하세요. URL에는 검색 " -"페이지의 url을 입력하세요. 사용자의 검색 쿼리는 URL에 ${query} 형식을 적절한 위치에 배치하여 만들수 있습니다.\n" -"예를 들어, 구글로 검색하려면:\n" -"이름: 구글\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "도움말" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "문자열 찾기" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "엔진 선택" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "엔진 관리" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "검색 " diff --git a/po/ku.po b/po/ku.po deleted file mode 100644 index d974f379c..000000000 --- a/po/ku.po +++ /dev/null @@ -1,2391 +0,0 @@ -# Kurdish translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2007-11-30 11:54+0000\n" -"Last-Translator: Erdal Ronahi \n" -"Language-Team: Kurdish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Torrentê lêzêde bike" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Lêzêdekirin" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Torrentê Rake" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Rakirin" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Bidomîne" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Behndan" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Jor" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Jêr" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Vebijark" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Pêvek" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Pel" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "Torrentê _lêzêde bike" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "_URLê lêzêde bike" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "Torrentên te_mamkirî rake" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Sererastkirin" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Pê_vek" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Nîşandan" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Darikê amûran" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Hûragahî" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Sitûn" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Mezinahî" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Rewş" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Leza Daxistinê" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Dema Mayî" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Alîkarî" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Vê bernameyê wergerîne" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Vê Bernameyê Wergerîne..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Daxistî:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Şandî:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Belavker:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Lez:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Tekilî:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Parçe:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statîstîk" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# ji pelan:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Mezinahî:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Rewşa trackerê:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nav:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Rêç:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Agahiyên Torrentê" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Kîtekît" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Pelên daxistî jê bibe" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Pelê .torrent jê bibe" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Nîşandan/Veşartin" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Torrentekê lê zêde bike..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "Pelî _Veke" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Hemû Hilbijêre" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Yekê jî Hilnebijêre" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Danexe" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Asayî" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Bilind" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Bilindtirîn" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Tercihên Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Peldankekê Hilbijêre" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Cihê Daxistinê" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrent" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Daxistin" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Ji:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Ber bi hundir re:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Neçalak\n" -"Çalak\n" -"Bi zordariyê" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Ber bi derve re:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Ast:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Tor" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Pêşkêşker" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Şîfre" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Navê bikarhêner" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Şîfre:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Yên Din" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Torrentê Rake" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Ser" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Berjor" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Berjêr" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Dawî" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Derketin" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Bêsînor" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Çalak" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Wekî din..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Nenas" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nav" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bayt pêwist in" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Pel" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Lez" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/la.po b/po/la.po deleted file mode 100644 index d46fc1cda..000000000 --- a/po/la.po +++ /dev/null @@ -1,2388 +0,0 @@ -# Latin translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2007-01-22 20:00+0000\n" -"Last-Translator: Matthias Benkard \n" -"Language-Team: Latin \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Magnitudo" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Donantes" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Socii" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Datur" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Ignotum" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nomen" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Coniunctiones" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Arcessere" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Donare" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Emptor Bittorrenti nominis Delugum" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Adverte! Omna data huius amnis delenda sunt!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Designatum" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Examinatur" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Omna data" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dies" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Emptor" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/lt.po b/po/lt.po deleted file mode 100644 index 92f214a51..000000000 --- a/po/lt.po +++ /dev/null @@ -1,2489 +0,0 @@ -# Lithuanian translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-06 11:16+0000\n" -"Last-Translator: Mindaugas \n" -"Language-Team: Lithuanian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Įdėti Torentą" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Pridėti" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Pašalinti Torentą" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Pašalinti" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Išvalyti skleidžiamus Torentus" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Išvalyti" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Pradėti arba pratęsti Torentą" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Pratęsti" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pauzė Torentui" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pauzė" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Pakelti Torrentą aukštyn eilėje" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Į Viršų" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Nuleisti Torrentą žemyn eilėje" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Žemyn" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Keisti Deluge nustatymus" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Nustatymai" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Įskiepiai" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Failas" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Įdėti Torrentą" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Įdėti Torrentą iš adreso" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Išvalyti Baigtus" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Redaguoti" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Į_skiepiai" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrentas" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "Ro_dymas" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Įrankių juosta" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detalės" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Stulpeliai" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Dydis" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Būsena" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Skleidėjai" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Šaltiniai" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Parsiuntimo greitis" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Išsiuntimo greitis" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Liko laiko" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Esamumas" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Dalinimosi santykis" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Žinynas" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Namų tinklalapis" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_DUK" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Bendruomenė" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Padėti išversti šią programą" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Išversti šią programą" - -#: glade/delugegtk.glade:539 -#, fuzzy -msgid "Runs the first-time configuration wizard" -msgstr "Paleidžia pirmojo karto konfigūracijos vedlį" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Paleisti konfigūracijos vediklį" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Parsiųsta:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Išsiųsta:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Skleidėjai:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Dalinimosi santykis:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Greitis:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Šaltiniai:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Liko:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Dalys:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Esamumas:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistika" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Failų skaičius:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Bendras dydis:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Trackeris:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Trackerio būsena:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Sekantis Announce:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Pavadinimas:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Kelias:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrento informacija" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detalės" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Ar jūs tikrai norite pašalinti pasirinktą(us) " -"torrentą(us) iš Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Ištrinti parsiųstus failus" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Ištrinti .torrent failą" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Rodyti/Slėpti" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Įdėti Torrentą..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Išvalyti užbaigtus" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Atidaryti failą" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Pasirinkti visus" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Panaikinti pasirinkimą" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Nesiųsti" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normalus" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Aukštas" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Aukščiausias" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Sujungti deluge trackerių sąrašus" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Šis torrentas jau yra įdėtas į Deluge, ar norite paimti iš jo trackerių " -"sąrašą ir įdėti į esamą torrentą?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge nustatymai" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Klausti kur saugoti kiekieną kartą" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Pasirinkite aplanką" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Visų „torrent“ failų saugojimo vieta:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Talpinti visus siuntimus į:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Siuntimo vieta" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Vieta, iš kurios automatiškai įkeliami „torrent“ failai:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Autoįkėlimas" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "Aktyvių torrentų skaičius, kurį deluge siųs. -1 yra neribotai." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maksimalus aktyvių torrentų skaičius:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" -"Ijungti galimybę pasirinkti siunčiamus failus prieš pradedant siuntimą" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Rodyti tik tuomet, kai torrente yra daugiau kaip 1 failas" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Padidinti prioritetą pirmai ir paskutinei daliai failams torrente" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Pradėti torrentus pristabdytus" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrentai" - -#: glade/preferences_dialog.glade:390 -#, fuzzy -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Tikslus paskirstymas rezervuoja visą reikiamą vietą torrent'o išsaugojimui " -"taip užkirsdamas kelią disko fragmentavimuisi." - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Naudoti pilną paskirstymą" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" -"Kompaktiškas paskirstymas paskirsto disko vietą tik tuomet, kai ji reikalinga" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Naudoti kompaktišką paskirstymą" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Paskirstymas" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Parsiuntimai" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Pastaba - Pokyčiai šiems nustatymams taps aktyvus, kai kitą kartą " -"paleisite deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Iš:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Į:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge paskirs skirtingą prievadą kiekvieną kartą." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Atsitiktiniai prievadai" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Patikrinti aktyvų prievadą" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktyvus prievadas:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "DHT gali padidinti šaltinių skaičių," - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Įjungti DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT prievadų peradresavimas" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Siuntėjų apsikeitimas" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Vietinių siuntėjų atpažinimas" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Papildomi Tinklo Nustatymai" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Įeinantis:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Išjungta\n" -"Įjungta\n" -"Priversta" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Išeinantis:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Kai įmanoma, užšifruoti visą duom. srautą" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Lygis:" - -#: glade/preferences_dialog.glade:931 -#, fuzzy -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Patvirtinimas\n" -"Visas srautas\n" -"Bet kuris" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Šifravimas" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Tinklas" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Įdėti torrenta į eilės apačią kai jis pradeda skleisti" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Įdėti naujus torrentus virš baigtųjų." - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Baigti skleidimą, kai torrentu dalijimosi santykis pasiekia:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Automatiškai išvalyti torrentus kurie pasiekia maks. dalijimosi santykį." - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Skleidimas" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Skleidimas" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Maksimalus susijungimo bandymų per sekundę skaičius. Didesnė reikšmė gali " -"sukelti kai kurių pigių maršrutizatorių lūžį. Kai reikšmė „-1“, tuomet " -"neribojama." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maksimalus susijungimo bandymų skaičius per sekundę" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "Maksimalus išsiuntimo kanalų sk. visiem torrentam. -1 yra neribotai" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "Maksimalus išsiuntimo greitis visiem torrentam. -1 yra neribotas." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "Maksimalus parsiuntimų greitis visiems torrentams. -1 yra neribotai" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maksimalus parsiuntimo greitis (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Maksimalus prisijungimų skaičius. -1 yra neribotai" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Prisijungimų maksimumas:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maksimalus išsiuntimo greitis (kiB/s)" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maksimalus išsiuntimo kanalų skaičius:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Maksimalus pusiau atvirų susijungimų skaičius. Didesnė reikšmė gali sukelti " -"kai kurių pigių maršrutizatorių lūžį. Kai reikšmė „-1“, tuomet neribojama." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maksimalus pusiau atvirų susijungimų skaičius:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Bendras duomenų srautas" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "Maksimalus išsiuntimo kanalų sk, per torrentą. -1 yra neribotai." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Maksimalus prisijungimų skaičius per torrentą. -1 yra neribotai" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Torrento duomenų srautas" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Duom. srautas" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Turi įtakos reguliariem bittorent šaltiniam" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Įjungtas" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Prievadas:" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Serveris:" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Joks\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 su autentiifkacija\n" -"HTTP\n" -"HTTP su autentifikacija" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Slaptažodis:" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Vart. Vardas:" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Tipas:" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Šaltinių tarpinis serveris" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Įjungtas" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Trackerio tarpinis serveris" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Įjungtas" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Tarpinis serveris" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Įjungtas" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Tinklinio skleidimo (web seed) tarpinis serveris" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Tarpiniai serveriai" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Įjungti sistemos dėklo ženkliuką" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Užveriant nukelti į sistemos dėklą" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Paleisti sisteminiame skydelyje" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Uždėti slaptažodį ant sistemos dėkliuko" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Slaptažodis:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Sistemos dėkliukas" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Naudoti tobulesnę progreso juostą (naudoja šiek tiek daugiau CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Detali progreso juosta" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "Deluge patikrins mūsų serverius ir pasakys ar yra atnaujinimų" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Perspėti apie atnaujinimus" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Atnaujinimai" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Padėkite mums pagerinti Deluge siųsdami savo Python ir PyGTK versijas, \n" -"OS ir procesoriaus tipus. Jokia kita informacija nebus siunčiama." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Sistemos informacija" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Kita" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Priverstinai pertikrinti" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Pra_tęsti" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pauzė" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Pašalinti Torrentą" - -#: glade/torrent_menu.glade:95 -#, fuzzy -msgid "_Tracker Options" -msgstr "_Trackerio nustatymai" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Atnaujinti trackerį" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Redaguoti trackerius" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Eilė" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Viršus" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Aukštyn" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Žemyn" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Apačia" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Atverti talpinimo katalogą" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Rodyti Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Pratęsti visus" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Sustabdyti visus" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Atsiuntimo greičio riba" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Išsiuntimo greičio riba" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Išeiti" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Redaguoti trackerius" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Trackerio redagavimas" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge failų pasirinkimas" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrent failas nebus platinamas tinkle be trackerių (DHT)" - -#: glade/files_dialog.glade:43 -#, fuzzy -msgid "Set the private flag" -msgstr "Nustatyti privačią vėliavėlę" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Pirmojo paleidimo derinimas" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Naudoti a_tsitiktinius prievadus" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Kiekvienąkart klausti, kur išsaugoti failą" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Visų atsiuntimų saugojimo vieta: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maksimalus aktyvių torrentų skaičius:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Neribota" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktyvuotas" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Kita.." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Parsiuntimo Greitis (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Išsiuntimo Greitis (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge yra užrakinta" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge yra užrakinta slaptažodžiu\n" -"Kad jūs galėtumėte pamatyti Deluge langą, prašom įvesti slaptažodį." - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Begalybė" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Nežinomas" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Pavadinimas" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Likęs laikas" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Esam." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Santykis" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Sustabdyta %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Eilėje %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "Yra naujesnė deluge versiją. Ar norite ją atsisiųsti?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Prisijungimai" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Siuntimas" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Išsiuntimas" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorent Klientas" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Pasirinkite katalogą parsiuntimui" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Įvyko klaida įdedant torrent rinkmeną. Galbūt jūsų .torrent rinkmena yra " -"sugadinta" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Nėra pakankamai laisvos disko vietos šio atsiuntimo užbaigimui." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Reikia disko vietos:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Yra disko vietos:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Įdėti torrentą iš adreso" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Įveskite adresą i .torrent rinkmeną" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Perspėjimas - visi šio torrento parsiųsti failai bus ištrinti!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Ar tikrai norite pašalinti visus skleidžiamuosius torrentus?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Eilėje" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Tikrinama" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Jungiasi" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Parsiunčiami metaduomenys" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Siunčiama" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Baigta" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Paskiriama" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "reikia baitų" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Nėra pakankamai disko vietos, kad užbaigt jūsų siuntimą." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Announce išsiųstas" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Announce Sėkmingas" - -#: src/core.py:774 -msgid "Alert" -msgstr "Įspėjimas" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP kodas" - -#: src/core.py:776 -msgid "times in a row" -msgstr "Kartų iš eilės" - -#: src/core.py:788 -msgid "Warning" -msgstr "Dėmesio!" - -#: src/files.py:77 -msgid "Filename" -msgstr "Rinkmenos pavadinimas" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioritetas" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Failų prioritetai gali būti naudojami tik tuomet, kai įjungtas pilnas " -"paskirstymas.\n" -"Nustatymuose pakeiskite šį pasirinkimą išjungdami kompaktišką paskirstymą, " -"tuomet pašalinkite ir iš naujo pridėkite šį torrentą." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Priedas" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Įjungtas" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Pasirinkite .torrent rinkmeną" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent rinkmenos" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Visos bylos" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Išorinė komanda" - -#: src/common.py:207 -msgid "not found" -msgstr "nerasta" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"parsisiųsti ir importuoti įvairius juoduosius sąrašus\n" -"\n" -"Dabar šis įskiepis palaiko PeerGuardian,\n" -"SafePeer ir eMule sąrašus. PeerGuardian 7zip rinkmenos\n" -"nėra palaikomos. Rinkmenos gali būti nurodomos kaip interneto\n" -"adresai arba iš lokalios failų sistemos\n" -"\n" -"Puslapis kur jūs galite rasti juoųjų sąrašų yra wikije:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Tekstas (Nesuspaustas)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "eMule IP sąrašas (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer tekstas (Zipped)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Nepavyko parsiųsti iš adreso" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Nepavyko atverti juodojo sąrašo failo" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Netinkamas failo tipas arba sugadintas juodojo sąrašo failas." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importuota" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP'ai" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Juodasis sąrašas" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "Įrašai" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Juodojo sąrašo adresas" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dienos" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Įkeliamas ir įdiegiamas juodasis sąrašas" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importuojama" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Atlikta" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Neteisinga versija" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Nustatyti torrentui norimą santykį" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Norimas santykis" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Nenustatyta" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Nenustatyta" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Norimas santykis" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP adresas" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klientas" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Atlikta" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrentų kūrėjas" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Šis torrentas bus sukurtas iš vieno failo" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Rinkmena:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Šis torrentas bus sukurtas iš katalogo." - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Katalogas:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Šaltinis" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Išsaugoti torrent rinkmeną kaip:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Įkelti šį torrentą į Deluge skleidimui" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Įdėti naują torrentą į eilę" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent Rinkmena" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackeriai" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Web skleidėjai" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Komentarai" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autorius" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -#, fuzzy -msgid "Set Private Flag" -msgstr "Nustatyti privačią vėliavėlę" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Kuo mažesnis dalių dydis, tuo efektyvesnis jų persiuntimas, tačiau .torrent " -"rinkmena bus didesnė." - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Dalies dydis:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Sudėtingiau" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Torrentų kūrimo įskiepis" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Naujas Torretas" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Naujas Torrentas" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Sukurti naują torrentą" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Išsaugoti rinkmeną kaip..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Jūs privalote pasirinkti šaltinį šiam torrentui" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Jūs privalote pasirinkti rinkmeną į kurią išsaugoti torrentą." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Torrentų perspėjimo nustatymai" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" -"Įjungti garsus įvykiams (reikainga „pygame“, negalima Win32 sistemoje)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Įjungti mirksintį sistemos dėklo ženkliuką" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Įjungti iššokantįjį pranešimą (reikalinga „python-notify“, negalima Win32 " -"sistemoje)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Mirksinti sisteminio skydelio piktogramą, kai torrentas baigtas siųsti " -"ir/arba iššokus pranešimui" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrentas baigtas" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Tinklo 'sveikatos' monitorius įskiepis\n" -"\n" -"Parašė Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Sveikumas: Geras]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Įvykių vedimo į žurnalą nustatymai" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Vesti įvykių žurnalą į failus" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Žurnalo failai" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Šaltinis užblokuotas" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blokas užbaigtas" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Blokas siunčiamas" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Dalis baigta" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Trackerio perspėjimas" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Trackerio įspėjimas" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Trackerio atsakymas:" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Trackerio announce" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Siuntėjo užblokavimo klaida" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Klaida byloje" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Neteisinga užklausa" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Siuntėjų pranešimai" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrentas baigtas" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Pasirinkti įvykius žurnalui" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Įvykių žurnalas" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "Įvykio žinutė: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "Torrentas: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Šaltinio žinutė" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "IP adresas: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "Klientas: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "Dalies indeksas: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "būsenos kodas: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Kartų iš eilės: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "Bloko indeksas: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "Šaltinio greitis: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Nustatykit norimą greičio ribojimą torrentui" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrento _siuntimo greitis" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrento išsiuntimo g_reitis" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrento išsiuntimo greitis (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrento parsiuntimo greitis (KiB/s)" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Tinklo aktyvumo grafikas\n" -"\n" -"Parašė: Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Grafikas" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progresas" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Failai" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Perkelti torrentą" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Pasirinkite aplanką, į kurį perkelsite failus" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Perkelti baigtus siuntimus į:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "Adresas:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Planuoklio nustatymai" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Prievado numeris" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Naujas slaptažodis" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Pakartokite slaptažodį" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Šablonas" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Mygtukų stilius" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Tekstas ir paveikslėliai" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Tik paveikslėliai" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Tik tekstas" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "jokių duomenų." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "Failų skaičius" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Apie" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Pridėti torrentą" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Pritaikyti" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Ištrinti atsiųstus failus." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Išjungti" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Atsiųsta" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Įjungti" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Klaida" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Liko" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Prisijungti" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Atsijungti" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Kitas pranešimas" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Išjungta" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Slaptažodis neteisingas, bandykite dar kartą" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pauzė visiems" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Dalys" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Perkelti eilėje žemiau" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Eilės pozicija" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Perkelti eilėje aukščiau" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Iš naujo paskelbti" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Pašalinti torrentą" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Pratęsti visus" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Nustatyti" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Greitis" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Pradėti" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrentų sąrašas" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Visas dydis" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Trackeris" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Trackerio būsena" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Išsiųsti torrentą" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Išsiųsta" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "URL" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekundės" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Srautas turi būti atnaujintas rankiniu būdu." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Išjungta" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Atnaujinimo intervalas" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Naujienų kanalai" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tipas" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Kanalas" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informacija" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Iš" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Sezonas" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Epizodas" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Neatitinka" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Metai" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Mėnuo" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Diena" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Įterpti torrentą eilės viršuje." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Nustatyti pauzės būseną." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Kai atitinka, ištrinti filtrą." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Pakeitimas" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Nuorodų perrašymas" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Turinys bus išsaugotas Deluge numatytajam aplanke, o jei toks nenustatytas, " -"bus paklausta, kurį aplanką pasirinkti." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge numatytasis" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Turinys bus automatiškai atsiųstas į nurodytą aplanką." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Pasirinkti:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Išvedimas" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtrai" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Rodyti mygtuką priemonių juostoje." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Sąsaja" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Gijomis (eksperimentinė)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Kanalų gavimas" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Sritis" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Kelias" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Reikšmė" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Slapukai" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Konfigūracija" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Valdyti paieškos įskiepius" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Pavadinimas:" - -#: plugins/Search/searchdlg.glade:123 -#, fuzzy -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Pridėti naują paieškos sistemą įvedant jos pavadinimą ir universalųjį adresą " -"(URL). Vartotojo užklausa paieškos metu pakeis ${query} dalį universaliajame " -"adrese. Paieškos sistemos pavyzdys: Pavadinimas - Google, URL - " -"http://www.google.com/search?q=${query} ." - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Pagalba" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Paieškos užklausa" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Pasirinkite varikliuką" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Valdyti varikliukus" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Ieškoti " diff --git a/po/lv.po b/po/lv.po deleted file mode 100644 index a25aa3901..000000000 --- a/po/lv.po +++ /dev/null @@ -1,2428 +0,0 @@ -# Latvian translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2007-10-29 13:18+0000\n" -"Last-Translator: Holmsss \n" -"Language-Team: Latvian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Pievienot torrentu" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Pievienot" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Aizvākt torrentu" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Novākt" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Izdzēst" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Atsākt" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Iepauzēt" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Pāŗvietot uz augšu" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Augšup" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Pārvietot uz leju" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Lejup" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Labot iestatījumus" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Uzstādījumi" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Spraudņi" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Fails" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Pievienot torrentu" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Pievienot no _adreses" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "Iz_dzēst pabeigtos" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Labot" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Spraudņi" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrents" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Skatīt" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "Rīkjosla" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "Papildinformācija" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Kolonnas" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Izmērs" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Statuss" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Devēji" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Iesaistītie" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Lejupielādes ātrums" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Augšupielādes ātrums" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Laiks Atlicis" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Pieejamība" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Dalīšanās koeficients" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Palīdzība" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Piedalies programmas tulkošanā" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "Piedalies programmas tulkošanā" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Lejupielādēts:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Augšupielādēts:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Devēji:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Dalīšanās attiecība:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Ātrums:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Iesaistītie:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Laiks atlicis:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Gabaliņi:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Pieejamība:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistika" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# faili:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Kopējais izmērs:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Trakeris:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Trakera statuss:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Nākamā pārziņošana:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nosaukums:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Ceļš" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Informācija par torrentu" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Sīkāka informācija" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Tiešām vēlaties dzēst attiecīgo " -"torrentu(s)?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Dzēst lejupielādētos failus" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Dzēst .torrent failu" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Rādīt/Paslēpt" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Pievienot torrentu..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Novākt pabeigtos" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Iezīmēt visus" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Atcelt iezīmējumu" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Nevajag lejupielādēt" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normāla" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Augsta" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Augstākā" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Apvienot trakeru sarakstus" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "Šāds torrents jau pastāv, vai vēlaties apvienot trakeru sarakstus?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge iestatījumi" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Katru reizi piedāvāt izvēlēties lejupielādes vietu" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Izvēlēties mapi" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Glabāt lejupielādētos failus:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Lejupielādes vieta" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Maksimālais vienlaicīgi aktīvo torrentu skaits. -1 nozīmē neierobežots." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maksimāli vienlaicīgi aktīvie torrenti:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Piedāvāt vispirms izvēlēties failus, kurus lejupielādēt" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Uzstādīt augstāku prioritāti pirmajām un pēdējām torrenta daļiņām" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrenti" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Lejupielādes" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Piezīme - labojumi uzstādījumos stāsies spēkā tikai nākamajā programmas " -"palaišanas reizē." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "No:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Uz:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge automātiski katru reizi izvēlēsies citu portu." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Gadījuma porti" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Pārbaudīt tekošo portu:" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Tekošais ports:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Dalītā kontrolsummu tabula var uzlabot kopējo pieslēgumu skaitu." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Izmantot Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT portu pārveides protokols" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Tīkla papildiespējas" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Ienākošais:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Atslēgts\n" -"Ieslēgts\n" -"Uzspiests" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Izejošais:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Ja iespējams, šifrēt visu plūsmu" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Līmenis:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Šifrēšana" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Tīkls" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Pārvietot torrentus uz saraksta beigām, kad tie ir pabeigti" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Pievienot jaunos torrentus saraksta sākumā" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Pārstāt piedāvāt torrentu, kad ir sasniegta attiecība:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Automātiski izdzēst torrentus, kas sasnieguši maksimālo dalīšanās attiecību:" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Piedāvāšana" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Piedāvāšana" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Maksimālais augšupielādes pieslēgvietu skaits. -1 nozīmē neierobežots." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maksimālais kopējais visu torrentu augšupielādes ātrums. -1 nozīmē " -"neierobežots." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maksimālais visu torrentu lejupielādes ātrums. -1 nozīmē neierobežots." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maksimālais lejupielādes ātrums (KiB/s)" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Maksimālais konekciju skaits. -1 nozīmē neierobežots." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maksimālais konekciju skaits:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maksimālais augšupielādes ātrums (KiB/s)" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Caurlaidība" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Ietekmē parastus bittorrent lietotājus" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Ports" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Serveris" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Nekāds\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Parole" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Lietotājvārds:" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxy tips" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Iesaistīto Proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Trakera proxy Proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Izmantot sistēmas paneļa ikonu" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Aizverot logu, minimizēt kā sistēmas paneļa ikonu" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Aizsargāt sistēmas paneļa ikonu ar paroli" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Parole:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Sistēmas panelis" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Citi" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Dzēst torrentu" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Atjaunot trakeri" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "Labot trakerus" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Novietojums rindā" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Pašā augšā" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Augšup" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Lejup" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Pašā lejā" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "Pārādīt Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Aizvērt" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Neierobežots" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktivizēts" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Citi..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Pieeja Deluge programmai ir slēgta" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Pieeja Deluge programmai ir aizsargāti ar paroli\n" -"Lai piekļūtu programmas logam, lūdzu ievadiet paroli" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Bezgalība" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Nezināms" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nosaukums" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Laiks atlicis" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Attiecība" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Iepauzēts %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Konekcijas" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Lejupielāde" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Augšupielāde" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrenta Klients" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Izvēlieties lejupielādes mapi" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "Kļūme pievienojot torrentu. Iespējams .torrent fails ir bojāts." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Nepazīstama torrentu dublicēšanās kļūda." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Nepieciešamā diska vieta:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Pieejamā diska vieta:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Pievienot torrentu no saites:" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Ievadiet saiti uz .torrent failu, kuru lejupielādēt" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Uzmanību - visi lejupielādētie faili šim torrentam tiks dzēsti!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Ierindots" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Pārbaudu" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Pieslēdzas" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Lejupielādē metadatus" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Lejupielādē" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Pabeigts" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Atvēlu" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "baiti nepieciešami" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Nepietiek diska vietas lai pabeigtu lejupielādi." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Ziņojums nosūtīts" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Ziņojums kārtībā" - -#: src/core.py:774 -msgid "Alert" -msgstr "Trauksme" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP kods" - -#: src/core.py:776 -msgid "times in a row" -msgstr "reizes rindā" - -#: src/core.py:788 -msgid "Warning" -msgstr "Brīdinājums" - -#: src/files.py:77 -msgid "Filename" -msgstr "Faila nosaukums" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioritāte" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Spraudnis" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Ieslēgts" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Izvēlieties .torrent failu" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent faili" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Visi faili" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Lejupielādē un importē dažādus bloķēto IP sarakstus.\n" -"\n" -"Pašreiz spraudnis atbalsta PeerGuardian (bināro un teksta), SafePeer un " -"Emule sarakstu formātus. PeerGuardian 7zip formāts netiek atbalstīts. Failus " -"var norādīt gan kā interneta adreses, gan lokālās failu sistēmas adreses.\n" -"\n" -"Lapuse ar norādēm uz bloķēto IP sarakstiem ir pieejama iekš viki:\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Teksta (nnesaspiests)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP saraksts (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Teksts (Zip formātā)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Nevaru lejupielādēt adreses saturu" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Nevaru atvērt bloķēto IP saraksta failu" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importēts" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Bloķēto IP saraksts" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "ieraksti" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Bloķēto IP saraksta adrese" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dienas" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Tiek lejupielādēts un instalēts bloķēto IP saraksts" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Notiek importēšana" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Pabeigts" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Kļūdains sākums" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Kļūdains kods" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Kļūdaina versija" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Norāda vēlamo dalīšanās attiecību torrentam." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "Vēlamā attiecība" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "Nav uzstādīts" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Nav uzstādīts" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Vēlamā attiecība" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP adrese" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klients" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Procenti pabeigti" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrenta autors" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Šis torrents tiks izveidots no viena faila" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Fails:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Šis torrents tiks izveidots no mapes" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Mape:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Saturs" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Saglabāt torrenta failu kā:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Ielādēt šo torrentu Deluge programmā piedāvāšanai" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Pievienot jaunu torrentu sarakstam" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrenta fails" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trakeri" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Komentāri" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autors" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Jo mazāki daļiņu izmēri, jo efektīvāka būs datu izplatīšana, taču pats " -".torrent fails būs pēc izmēra lielāks" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Daļiņas izmērs:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Sīkāki uzstādījumi" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Torrentu izveides spraudnis" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "Jau_ns torrents" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Jauns torrents" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Izveidot jaunu torrentu" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Saglabāt failu kā..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Jums jānorāda torrenta saturs." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Jums jānorāda vieta, kur saglabāt torrenta failu." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "Tīkla stāvokļa pārbaudītāja spraudnis" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Stāvoklis: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Faila kļūda" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Nederīgs pieprasījums" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Tīkla aktivitātes grafika spraudnis\n" -"Izveidojis Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Grafiks" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progress" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Faili" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Pārvietot lejupielādētos failus uz:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "Adrese:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Augšupielādes pieslēgvietas:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Nākamā paziņošana" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Gabaliņi" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Kopējais izmērs" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Trakeris" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Trakera statuss" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekundes" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "Adrese" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Barotnes" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Barotne" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtri" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Pārvaldīt meklēšanas spraudņus" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nosaukums:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Lai pievienotu jaunu meklēšanas dzinēju, ievadiet tā nosaukumu un adresi. " -"Lai norādītu vietu, kurā jāievieto lietotāja atslēgvārdi izmantojiet iezīmi " -"${query}.\n" -"Piemēram, lai pievienotu Google dzinēju būtu jāievada:\n" -"Nosaukums: Google\n" -"Adrese: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Palīdzība" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Meklēšanas atslēgvārdi" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Izvēlieties meklēšanas dzinējus" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Pārvaldīt meklēšanas dzinējus" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Meklēt " diff --git a/po/mk.po b/po/mk.po deleted file mode 100644 index 37d9b87a4..000000000 --- a/po/mk.po +++ /dev/null @@ -1,2412 +0,0 @@ -# Macedonian translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-27 10:14+0000\n" -"Last-Translator: silfiriel \n" -"Language-Team: Macedonian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Додај Торент" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Додај" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Отстрани Торент" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Отстрани" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Исчисти Делени Торенти" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Исчисти" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Започни или Продолжи Торент" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Продолжи" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Паузирај Торент" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Пауза" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Подреди Погоре" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Нагоре" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Подреди Подолу" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Надолу" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Промени Преференции" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Преференции" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Приклучоци" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Датотека" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Додај Торент" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Додај _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "Исчисти Завршени" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Уреди" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Дод_атоци" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Торент" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Поглед" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Алатник" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Детали" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Колони" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Големина" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Статус" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Сејачи" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Пријатели" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Брзина на симнување" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Брзина на качување" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Преостанато време" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Достапност" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Сооднос на делење" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Помош" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Донирај за Развој на Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Донирај" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Домашна Страна" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_ЧПП" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Заедница" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Помогни за превод на Deluge" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Преведи ја оваа апликација" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Го стартува волшебникот за прв-пат конфигурирање" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Стартува Волшебник за Конфигурација" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Преземено" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Качени" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Сејачи:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Сооднос:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Брзина:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Пријатели:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "ПВЗ:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Делови:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Достапност:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Статистики:" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# на датотеки:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Вкупна големина:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Тракер:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Статус на Тракерот:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Следна Најава:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Име:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Патека:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Инфо за торентот" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Детали" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Дали сте сигурни дека сакате да ги отстраните " -"селектираните торенто од Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Избриши преземени датотеки" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Избриши го торентот" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Покажи/Скри" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Додај Торент..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Исчисти Завршени" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Отвори датотека" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Избери сѐ" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Деселектирај ги сите" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Не преземај" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Нормално" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Високо" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Највисоко" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "Торентот веќе постои. Сакате да ги додадете тракерите во листата?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge Преференции" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Прашај каде да се зачува секое преземање" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Одбери папка" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Зачувај ги торентите во:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Зачувај ги преземањата во:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Локација за Преземања" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "максимум истовремени активни торенти" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Покажи само ако торентот има повеќе од 1 датотека" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Започни паузирани торенти" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Торенти" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Користи целосна алокација" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Користи компактна алокација" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Алокација" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Преземања" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Од:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "До:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Случајна Порта" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Тестирај Активна Порта" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Активна Порта" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Пријателска Размена" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Локална детекција" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Мрежни Додатоци" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Исклучено\n" -"Вклучено\n" -"Присили" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Ниво:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Енкрипција" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Мрежа" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Прекини со сеење кога соодносот ќе достигне:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Број на часови" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Сејам" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Сеење" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Сообраќај" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Порта" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Сервер" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Лозинка" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Корисничко име" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Овозможи икона во сис. лента" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Лозинка:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Друго" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Пр_одолжи" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Паузирај" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Отстрани Торент" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Освежи Тракер" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Нагоре" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Надолу" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Напушти" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"Copy text \t\n" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Неограничено" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Друго..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Бескрајно" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Непознато" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Име" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ЕТА" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Сооднос" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Врски" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Преземи" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Качи" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Се поврзувам" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Преземам" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Завршено" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "Внимание" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "Предупредување" - -#: src/files.py:77 -msgid "Filename" -msgstr "Име на датотека" - -#: src/files.py:82 -msgid "Priority" -msgstr "Приоритет" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Додаток" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Овозможено" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Торент датотеки" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Сите датотеки" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Прикачени" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "секунди" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Оневозможено" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Канали" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Тип" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Канал" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Информација" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Од" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Сезона" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Епизода" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Година" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Месец" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Ден" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Преземање" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Замена" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Шаблон" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Излезен резултат" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Филтри" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Интерфејс" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Домејн" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Патека" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Вредност" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Колачиња" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Конфигурација" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Име:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Помош" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Пребарај низа" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/ms.po b/po/ms.po deleted file mode 100644 index f7b1bf756..000000000 --- a/po/ms.po +++ /dev/null @@ -1,2471 +0,0 @@ -# Malay translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-02-07 10:20+0000\n" -"Last-Translator: Low Kian Seong \n" -"Language-Team: Malay \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Tambah Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Tambah" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Buang Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Buang" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Bersih Torrent Penyemai" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Padam" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Mula Torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Sambung" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Henti Sebentar Torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -#, fuzzy -msgid "Pause" -msgstr "Rehat" - -#: glade/delugegtk.glade:106 -#, fuzzy -msgid "Queue Torrent Up" -msgstr "Torrent Maju ke Atas" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Naik" - -#: glade/delugegtk.glade:120 -#, fuzzy -msgid "Queue Torrent Down" -msgstr "Maju Torrent ke Bawah" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Turun" - -#: glade/delugegtk.glade:142 -#, fuzzy -msgid "Change Deluge preferences" -msgstr "Ubahsuai Ketetapan Deluge" - -#: glade/delugegtk.glade:143 -#, fuzzy -msgid "Preferences" -msgstr "Preferences" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugin" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Fail" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Tambah Torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Tambah _URL" - -#: glade/delugegtk.glade:216 -#, fuzzy -msgid "_Clear Completed" -msgstr "_Kemas Selesai" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Edit" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_gins" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Papar" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Toolbar" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Perincian" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Kolum" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Saiz" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Status" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Penyemai-penyemai" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Rakan" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -#, fuzzy -msgid "Down Speed" -msgstr "Laju Turun" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Laju Naik" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Masa Tinggal" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "kesedia adaan" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Kadar Kongsi" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Bantuan" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_halamanrumah" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_komuniti" - -#: glade/delugegtk.glade:515 -#, fuzzy -msgid "Help translate this application" -msgstr "Bantu terjemah aplikasi ini" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Terjemah Aplikasi Ini" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Jalankan configuration wizard buat pertama kali" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Jalan Konfigurasi Bijak" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Jumlah Muat-Turun:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "<>Jumlah Muat-Naik:" - -#: glade/delugegtk.glade:827 -#, fuzzy -msgid "Seeders:" -msgstr "Penyumbang:" - -#: glade/delugegtk.glade:845 -#, fuzzy -msgid "Share Ratio:" -msgstr "Kadar kongsi:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -#, fuzzy -msgid "Speed:" -msgstr "Kelajuan:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Penerima:" - -#: glade/delugegtk.glade:925 -#, fuzzy -msgid "ETA:" -msgstr "Anggaran selesai:" - -#: glade/delugegtk.glade:942 -#, fuzzy -msgid "Pieces:" -msgstr "Cebisan:" - -#: glade/delugegtk.glade:980 -#, fuzzy -msgid "Availability:" -msgstr "Kebolehsediaan:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistik" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# gagal" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "<>Saiz Keseluruhan:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Pengesan:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Status Pengesan:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Pengumuman Seterusnya:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nama:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "<>Haluan:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Info Torrent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Keterangan" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Adakah anda pasti untuk buang torrent yang dipilh " -"dari Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Buang fail yang dimuatturun" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Buang fail .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Papar/Sembunyi" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Tambah Torrent" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Clear Finished" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Buka Fail" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Pilih Semua" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Unselect Semua" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Jangan muat turun" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Biasa" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -#, fuzzy -msgid "High" -msgstr "Tinggi" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -#, fuzzy -msgid "Highest" -msgstr "Tertinggi" - -#: glade/merge_dialog.glade:7 -#, fuzzy -msgid "Deluge Merge Tracker Lists" -msgstr "Senarai Merge Tracker Deluge" - -#: glade/merge_dialog.glade:23 -#, fuzzy -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent telah dikesan dalam Deluge, adakah anda mahu gabung senarai tracker?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge Preferences" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Tanya dimana mahu disimpan setiap muat turun" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Pilih Folder" - -#: glade/preferences_dialog.glade:90 -#, fuzzy -msgid "Store all torrent files in:" -msgstr "Simpan semua file-file torrent dalam:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Simpan semua muat turun dalam:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Lokasi Muat turun" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Bilangan torrent aktif Deluge akan jalankan. Set kepada -1 untuk tidak " -"terhad." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maksimum torrent aktif serentak" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Enable pilih fail torrent sebelum muat turun." - -#: glade/preferences_dialog.glade:303 -#, fuzzy -msgid "Only show if torrent has more than 1 file" -msgstr "Tunjuk jika torrent lebih dari satu file" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Utamakan cebisan awal dan akhir fail dalam torrent" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Guna Full Allocation" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Guna Compact Allocation" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Allocation" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Muat Turun" - -#: glade/preferences_dialog.glade:502 -#, fuzzy -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Perhatian - Pertukaran setting akan digunakan selepas restart Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Dari:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Kepada:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" -"Deluge akan memilih port berlainan secara automatik setiap kali digunakan." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Random Ports" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Periksa Port Aktif" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Active Port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Enable Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Port Mapping Protocol" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Network Extras" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Inbound:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Disabled\n" -"Enabled\n" -"Forced" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Outbound:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Prefer to encrypt the entire stream" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Level:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Handshake\n" -"Full Stream\n" -"Either" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Encryption" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Rangkaian" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Bariskan torrent ke bawah apabila mula seeding" - -#: glade/preferences_dialog.glade:1037 -#, fuzzy -msgid "Queue new torrents above completed ones" -msgstr "Bariskan torrent baru atas yang sudah selesai" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Berhenti seeding torrent apabila share ratio sampai:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Bersih torrent yang sampai share ratio maksimum secara automatik" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -#, fuzzy -msgid "Maximum Connection Attempts per Second:" -msgstr "Cubaan maksimum sambungan per saat:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Had slot muat naik maksimum untuk semua torrent. Set -1 untuk tak terhad." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Had kelajuan muat naik maksimum untuk semua torrent. Set -1 untuk tidak " -"terhad." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Had kelajuan muat turun maksimum untuk semua torrent. Set -1 untuk tak " -"terhad." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Kelajuan Muat turun Maksimum (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Maksimum connection dibenarkan. Set -1 untuk tak terhad." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maximum Connections:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Kelajuan Muat naik Maksimum (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Slot Muat naik Maksimum:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maximum Half-Open Connections:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Global Bandwidth Usage" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "Had slot muat naik maksimum per torrent. Set -1 untuk tak terhad." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Bilangan connection maksimum per torrent. Set -1 untuk tak terhad." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Per Torrent Bandwidth Usage" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Bandwidth" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Memberi kesan pada kawan bittorrent biasa" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Kata laluan" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Username" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxy type" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxies" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Enable system tray icon" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimize to tray on close" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Start in tray" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Password protect system tray" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Kata laluan:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "System Tray" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge akan memeriksa pelayan kami dan akan memberitahu anda jika versi baru " -"telah dikeluarkan." - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Updates" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Bantulah kami membaiki deluge dengan menghantar versi Python dan PyGTK, OS " -"dan jenis prosessor anda. Tiada informasi lain akan dihantar." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Informasi Sistem" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Memaksa pemeriksaan semula" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Re_sume" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pause" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Buang Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Update Tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Edit Trackers" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Queue" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Top" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Up" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Down" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Bottom" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Open Containing Folder" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Show Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Resume All" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Hentikan semua sementara" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Had laju muat turun" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Had laju muat atas" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Keluar" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Edit Trackers" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Tracker Editing" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Pemilihan Fail Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -#, fuzzy -msgid "Set the private flag" -msgstr "setkan bendera peribadi" - -#: glade/wizard.glade:10 -#, fuzzy -msgid "First Launch Configuration" -msgstr "Konfigurasi kali pertama" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Guna _Random Ports" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Tanyakan setiap kali mana fail akan disimpan" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Simpan semua muat-turun dalam: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Torrent Aktif Maksimum" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Kelajuan Talian Muat Naik Anda:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Tak terhad" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Telah diaktifkan" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Lain-lain..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Kelajuan Muat turun (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Kelajuan Muat naik (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge telah dikunci" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge dilindungi dengan kata laluan.\n" -"Untuk melihat window Deluge, sila masukkan kata laluan anda" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infinity" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Tidak Diketahui" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nama" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Avail." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Ratio" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Paused %s" - -#: src/interface.py:955 -#, fuzzy, python-format -msgid "Queued %s" -msgstr "Aturan %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Terdapat versi baru Deluge. Mahukah anda melawat halaman muatturun kami ?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Connections" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Muat turun" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Muat naik" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent Client" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Pilih direktori muat turun" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Unknown duplicate torrent error." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Tidak terdapat ruang cukup untuk menamatkan muatturun anda." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Ruang diperlukan" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Ruang yang ada" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Tambah torrent dari URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Masukkan URL bagi torrent untuk dimuat turun" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Amaran - semua fail yang telah dimuat turun untuk fail ini akan dihapus!" - -#: src/interface.py:1545 -#, fuzzy -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Adakah anda pasti untuk buang semua seeding torrent?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Queued" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Checking" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Connecting" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Downloading Metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Downloading" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Finished" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Allocating" - -#: src/core.py:138 -#, fuzzy -msgid "bytes needed" -msgstr "bytes dikehendaki" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Tidak terdapat ruang cukup untuk menamatkan muatturun anda." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP code" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "Amaran" - -#: src/files.py:77 -msgid "Filename" -msgstr "Filename" - -#: src/files.py:82 -msgid "Priority" -msgstr "Keutamaan" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Enabled" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Pilih fail torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Fail torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Semua fail" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "tidak ditemui" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "tidak dapat muat-turun URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Tidak dapat membuka fail senarai sekatan" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Fail salah jenis atau fail senarai sekatan yang rosak" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP-IP" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Senarai Sekatan" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Pautan-pautan senarai sekatan" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Selesai" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -#, fuzzy -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Kami mengharapkan fail gzip tetapi bukan itu yang dihantar, mungkin fail " -"rosak. Cuba olah senarai sekatan." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Kod magik salah" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Versi salah" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Alamat IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klien" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Peratusan Siap" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Pencipta torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Torrent ini akan dibuat daripada direktori" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Folder:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Sumber" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Simpan fail torrent sebagai:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Tambah torrent baru pada aturan" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Fail torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Komen-komen" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Penulis" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Saiz kepingan" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Torrent Baru" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Torrent Baru" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Cipta Torrent Baru" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Simpan fail ini sebagai..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Anda perlu memilih salah sumber bagi torrent ini" - -#: plugins/TorrentCreator/__init__.py:128 -#, fuzzy -msgid "You must select a file to save the torrent as." -msgstr "Anda harus memilih fail yang anda hendak menyimpan torrent sebagai" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent habis" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Kesihatan: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Kawan disekat" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Sekatan habis" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Muatturun disekat" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Permintaan salah" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Pesanan dari kawan" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "klien " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "kod status " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "kelajuan kawan: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Kelajuan Muatturun torrent (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graf" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progres" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Terdapat masalah semasa memulakan fail" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Fail-fail" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Tambah benih jaringan" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Tambah benih jaringan" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Nombor port" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Kata Laluan Baru" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Kata Laluan Baru(sahkan)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Templat" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Gaya Butang" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Gambar sahaja" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Sahkan kata laluan <> kata Laluan Baru\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "alih bahasa sesuatu" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "tiada data" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Tentang" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Tambah torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Laksanakan" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Buang file yang dimuatturun" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Matikan" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Hidupkan" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Ralat" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Kata Laluan salah, cuba lagi" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Hentikan semua sementara" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Posisi di aturan" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Buang torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Mulakan semua balik" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Kelajuan" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Mula" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Hantar" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Jumlah Saiz" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Penjejak" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Status penjejak" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Muat atas torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Telah dimuatatas" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "saat" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Pilih enjin anda" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Carian " diff --git a/po/nb.po b/po/nb.po deleted file mode 100644 index ab66e21d3..000000000 --- a/po/nb.po +++ /dev/null @@ -1,2594 +0,0 @@ -# Norwegian Bokmål translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-19 22:58+0000\n" -"Last-Translator: Kjetil Rydland \n" -"Language-Team: Norwegian Bokmål \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Legg til Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Legg til" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Fjern Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Fjern" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Fjern delte Torrenter" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Tøm" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Start eller fortsett torrenten" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Gjenoppta" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pause torrenten" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pause" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Flytt torrent opp i kø" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Opp" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Flytt torrent ned i kø" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Ned" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Forandre deluges innstillinger" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Innstillinger" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Programutvidelser" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Fil" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Legg til torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Legg til _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Fjern ferdige" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Rediger" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Utvidelser" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Vis" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Verktøylinje" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detaljer" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Kolonner" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Størrelse" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Status" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Delere" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Nedlastere" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Nedhastighet" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Opphastighet" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Tid som gjenstår" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Tilgjengelighet" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Delingsforhold" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Hjelp" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Donér penger til utviklingen av Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Donér" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Hjemmeside" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "Brukersamfunn" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Hjelp til med å oversette dette programmet" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "Hjelp til med å overse_tte dette programmet" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Kjør veiviser for førstegangskonfigurering" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "Kjør veiviser for førstegangskonfigu_rering" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Lastet ned:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Lastet opp:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Delere" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Delingsgrad:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Hastighet:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Nedlastere:" - -#: glade/delugegtk.glade:925 -#, fuzzy -msgid "ETA:" -msgstr "Tid igjen" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Deler:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Tilgjengelighet:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistikk" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Antall filer:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Total Størrelse:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Tracker Status:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Neste Annonsering:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Navn:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Sti:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrentinformasjon" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detaljer" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Er du sikker på at du vil fjerne de valgte " -"torrent(ene) fra Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Slett nedlastede filer" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Slett .torrent-fil" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Vis/Skjul" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Legg til en Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Fjern Ferdige" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Åpne fil" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Velg alle" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Velg bort alle" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Ikke last ned" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Høy" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Høyest" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Flett deluge trackerlister" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrenten er allerede oppdaget i Deluge. Ønsker du å flette trackerlistene?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge instillinger" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Spør hvor hver nedlasting skal lagres" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Velg en mappe" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Lagre alle torrentfiler i:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Lagre alle nedlastinger i:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Nedlastingsplassering" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Last automatisk alle torrentfiler i:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Last automatisk" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Antallet aktive torrenter Deluge vil kjøre, Sett til -1 for uendelig." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Flest aktive torrents på samme tid:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Aktivér valg av filer for torrenter før lasting:" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Vis kun hvis torrenten har mer enn 1 fil" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Prioritér de første og siste bitene av filene i torrenten" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Start torrenter i pausemodus" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrenter" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Full reservasjon reserverer all nødvendig diskplass på forhånd, slik at man " -"ungår fragmentering." - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Bruk full reservasjon" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Kompakt reservasjon reserverer diskplass etter behov" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Bruk kompakt reservasjon" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Reservasjon" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Nedlastinger" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Merk at forandringene ikke trer i kraft før neste gang Deluge startes." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Fra:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Til:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge vil automatisk velge en tilfeldig port hver gang." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Tilfeldige porter" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Test valgte port" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktiv Port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Distribuert hashtabell kan forbedre mengden av aktive tilkoblinger" - -#: glade/preferences_dialog.glade:703 -#, fuzzy -msgid "Enable Mainline DHT" -msgstr "Aktiver Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal \"Plug&Play\"" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT portmappingsprotokoll" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Nedlasterutveksling" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Lokal nedlasteroppdagelse" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Nettverks Ekstraer" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Innkommende:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Av\n" -"På\n" -"Tvunget" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Utgående:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "foretrekk kryptering av hele strømmen" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Nivå:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Oppkobling\n" -"Hele overføringen\n" -"En av delene" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Kryptering" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Nettverk" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Flytt torrenter til bunnen av køen når de begynner å dele" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Legg til nye torrenter foran ferdige i køen" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Stopp deling av torrenter når delingsraten når:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Automatisk fjern torrenter som har nådd valgte delingsrate" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Avslutt deling av torrent når deletiden når:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Antall timer" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "Fjern torrent automatisk når maksimal deletid er nådd" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Deling" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Deling" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Høyeste antall tilkoblingsforsøk per sekund. En høy verdi kan krasje noen " -"billige rutere. Sett til -1 for uendelig." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Høyeste antall tilkoblingsforsøk per sekund:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Høyeste antall opplastinagsplasser for alle torrenter. Sett til -1 for " -"uendelig." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Høyeste opphastighet for samtlige torrenter. Sett til -1 for uendelig." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Høyeste nedlastingshastigheten for samtilge torrenter. Sett til -1 for " -"uendelig." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Høyeste nedlastingshastighet (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Høyeste antall tillatte tilkoblinger. Sett til -1 for uendelig." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Høyeste antall tilkoblinger:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Høyeste opplastningshastighet (KiB/s)" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Høyeste antall upplastningsplasser:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Høyeste antall halvåpne tilkoblinger, En høy verdi kan krasje noen billige " -"rutere. Sett til -1 for uendelig" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Høyeste antall halvåpne tilkoblinger:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Global bruk av båndbredde" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Høyeste antall opplastingsplasser per torrent. Sett til -1 for uendelig" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Høyeste antall tilkoblinger per torrent. Sett til -1 for uendelig." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Båndbreddebruk per torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Båndbredde" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -#, fuzzy -msgid "Affects regular bittorrent peers" -msgstr "Rammer vanlige bittorent-nedlastere" - -#: glade/preferences_dialog.glade:1620 -#, fuzzy -msgid "Peer Proxy" -msgstr "Nedlastingsproxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Ingen\n" -"Socksv4\n" -"Socksv5 med autenisering\n" -"HTTP\n" -"HTTP med autenisering" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Passord" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Brukernavn" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Mellomtjener-type" - -#: glade/preferences_dialog.glade:1782 -#, fuzzy -msgid "Peer Proxy" -msgstr "Nedlastingsproxy" - -#: glade/preferences_dialog.glade:1815 -#, fuzzy -msgid "Tracker Proxy" -msgstr "Trackerproxy" - -#: glade/preferences_dialog.glade:1977 -#, fuzzy -msgid "Tracker Proxy" -msgstr "Trackerproxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT-proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT-proxy" - -#: glade/preferences_dialog.glade:2205 -#, fuzzy -msgid "Web Seed Proxy" -msgstr "Web deleproxy" - -#: glade/preferences_dialog.glade:2367 -#, fuzzy -msgid "Web Seed Proxy" -msgstr "Web deleproxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Mellomtjenere" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Bruk systemikonfeltet" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimer til menylinje ved avslutt" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Start i systemkurv" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Passordbeskytt systemkurv" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Passord:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Varslingsområde" - -#: glade/preferences_dialog.glade:2582 -#, fuzzy -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Bruk den avanserte fremdriftsviseren (bruker litt mer prosessor/minne)" - -#: glade/preferences_dialog.glade:2593 -#, fuzzy -msgid "Detailed Progress Bar" -msgstr " Detaljert fremdriftsviser" - -#: glade/preferences_dialog.glade:2627 -#, fuzzy -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "Deluge vil sjekke om det har kommet en ny utgave" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Varsle meg om nye utgaver" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Oppdateringer" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Hjelp oss å forbedre Deluge ved å sende oss dine versjoner\n" -"av Python, PyGTK og OS samt prosessortype. Ingen annen\n" -"informasjon blir sendt." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "System Informasjon" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Annet" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Tving ny sjekk" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Fort_sett" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pause" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Fjern Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Trackervalg" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Oppdatér Tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "R_ediger Trackere" - -#: glade/torrent_menu.glade:138 -#, fuzzy -msgid "_Scrape Tracker" -msgstr "_Skrap tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Kø" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Topp" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Opp" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Ned" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Bunn" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Åpne målmappe" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Vis Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "Fo_rtsett Alle" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Pause alle" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Nedlastingshastighet" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Opplastingshastighet" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Avslutt" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Endre trackere" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Endring av tracker" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge filvalg" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" -"Torrenten vil ikke bli distribuert på the trackerløse (DHT) nettverket" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Markér som privat" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Første kjøring-konfigurasjon" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Denne vegviseren vil hjelpe deg å stille inn Deluge etter dine ønsker. " -"Dersom Deluge er nytt for deg, legg merke til at mye av Deluge sin " -"funksjonalitet og muligheter finnes som plugins. Disse plugin'ene finner du " -"ved å klikke på knappen \"Programutvidelser\" på oppgavelinjen, eller ved å " -"velge \"Redigér\" fra menyen, deretter \"Utvidelser\"." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge trenger en mengde porter det kan bruke til å lytte etter " -"tilkoblinger. Standard porter for bittorrent er 5881-6889, men ettersom " -"flere netttilbydere blokkerer disse, oppfordres du til å velge noen andre, " -"gjerne mellom 49152 og 65535. Eventuelt kan du la Deluge plukke ut " -"tilfeldige porter for deg." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Bruk _tilfeldige porter" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Ønsker du at Deluge automatisk skal laste ned til en valgt katalog, eller " -"ønsker du å bli spurt hver gang?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Spør hvor hver fil skal lagres" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Lagre alle nedlastinger i: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"vennligst velg opplastingshastigheten for din tilkobling, som vi vil bruke " -"til å foreslå verdier for innstillingene under" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maksimalt antall aktive torrents:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Din linjehastighet utad:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Hjelp oss å forbedre Deluge ved å sende oss hvilke versjoner av Python, " -"PyGTK\n" -"og operativsystem samt prosessor du bruker. Ingen annen informasjon blir " -"sendt." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Deluge klarte ikke å identifisere din nettleser. Sjekk at du har python-" -"gnome2-extras installert, eller forsøk å sette dine miljøvariabler " -"LD_LIBRARY_PATH og MOZILLA_FIVE_HOME til /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Ubegrenset" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktivert" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Annet ..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Nedlastingshastighet (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Opplastingshastighet (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge er låst" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge er passordbeskyttet.\n" -"For å vise vinduet, vennligst skriv dit passord" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Evig" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Ukjent" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Navn" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Tid igjen" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Tilgj." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Rate" - -#: src/interface.py:760 -#, fuzzy -msgid "Choose a directory to switch torrent source to" -msgstr "Velg hvilken mappe du vil bytte torrentkilde til" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Slett gammel torrentkilde?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Pauset %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Lagt %s i køen" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Det finnes en nyere utgave av Deluge. Vil du gå til nedlastingssiden?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Tilkoblinger" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Nedlastning" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Opplastning" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent-klient" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Velg lagringsplass" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"En feil oppsto under innlastingen av torrenten. Det er mulig at .torrent-" -"filen din er korrupt." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Ukjent duplikat torrent feil." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Det er ikke nok ledig plass tilgjengelig for å fullføre nedlastingen." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Nødvendig diskplass:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Tilgjengelig diskplass:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Legg til en torrent fra URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Skriv inn URL til torrenten du vil laste ned" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Advarsel - alle nedlastede filer for denne torrenten vil bli slettet!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Er du sikker på at du vil fjerne alle delende torrents?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Lagt i kø" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Sjekker" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Kobler til" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Henter metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Laster ned" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Ferdig" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Tilordner" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes nødvendig" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Det er ikke nok ledig diskplass til å fullføre nedlastingen din." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Kunngjøring sendt" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Kunngjøring OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Varselmelding" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP-kode" - -#: src/core.py:776 -msgid "times in a row" -msgstr "ganger på rad" - -#: src/core.py:788 -msgid "Warning" -msgstr "Advarsel" - -#: src/files.py:77 -msgid "Filename" -msgstr "Filnavn" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioritet" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Filprioriet kan bare bli satt om man bruker full allokering.\n" -"Vennligst slå av kompakt allokering i innstillingene, fjern torrenten og " -"legg den til på nytt." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Programtillegg" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Aktiv" - -#: src/dialogs.py:445 -#, fuzzy -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge er fri programvare. Du kan videreføre og/eller\n" -"endre programmet under betingelsene av GNU General Public\n" -"License, publisert av Free Software Foundation,\n" -"enten versjon 2 av lisensen, eller (etter ditt ønske) enhver\n" -"nyere versjon.Deluge distribueres i håp om at det\n" -"kan komme til nytte, men UTEN NOEN GARANTIER, uten engang\n" -"å implisere SALGBARHET eller BRUK \n" -"FOR NOE SPESIELT FORMÅL. Se GNU General\n" -"Public License for mer informasjon. Du bør ha mottatt\n" -"en kopi av GNU General Public License sammen med\n" -"Deluge, men om ikke, skriv til Free Software Foundation, \n" -"Inc., 51 Franklin St, Fifth Floor Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Velg en torrent-fil" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent-filer" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Alle filer" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Ekstern kommando" - -#: src/common.py:207 -msgid "not found" -msgstr "ikke funnet" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Last ned og importer forskjellige IP svartelister.\n" -"For øyeblikket håndterer denne plugin'en PeerGuardian (binær og tekst),\n" -"SafePeer og Emule lister. PeerGuardian 7zip filer er ikke støttet. Filer " -"kan\n" -"beskrives med en URL eller en sti på det lokale filsystemet.\n" -"En side med lenker til svartelister er tilgjengelig på wikiet:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Tekst (Ikke komprimert)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IPliste (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Tekst (Zippet)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Kunne ikke hente URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Kunne ikke åpne svarteliste" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Feil filtype eller ødelagt svarteliste." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importert" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP-er" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blokkeringsliste" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "innlegg" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL til blokkeringsliste" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Last ned ny blokkeringsliste hver" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dager" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Laster og installerer blokkeringsliste" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importerer" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Fullfør" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Fikk formatfeil for zipfilen:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Vi forventet en gzip-komprimert fil, men ikk ikke det, eller kanskje filen " -"er ødelagt. Vennligst endre dine innstillinger av svartelisten" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Ugyldig leder" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Ugyldig magikode" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Ugyldig versjon" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Sett det ønskede delingsforholdet for en torrent" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Ønsket rate" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Ikke satt" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Ikke satt" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Ønsket rate" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Denne viser deg alle deltakerne knyttet til hver torrent og viser deres ip, " -"land, klient, prosent fullført, opplastings- og nedlastingshastighet.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP-adresse" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klient" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Prosent fullført" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrentskaper" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Denne torrenten vil bli opprettet fra en enkelt fil" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Fil:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Denne torrenten vil bli opprettet fra en mappe" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Mappe:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Kilde" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Lagre torrentfil som:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Åpne denne torrenten i Deluge for deling" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Legg til ny torrent i kø" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrentfil" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackere" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -#, fuzzy -msgid "Web Seeds" -msgstr "Web-Delere" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Kommentarer" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr " Forfatter " - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Aktiver Privat-flagget" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Jo mindre deler du velger, jo mer effektive vil overføringene bli, men selve " -"\".torrent\"-filen blir større." - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Størrelse på delene:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Avansert" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "En utvidelse for oppretting av torrenter" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Ny torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Ny torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Lag ny torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Lagre fil som..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Du må velge en kilde for torrenten." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Du må velge en fil å lagre torrenten til." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Innstillinger for torrentvarsler" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Aktiver hendelseslyder (krever pygame, ikke tilgjengelig på Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Aktiver blinkende systemikon" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "Ak" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"La ikon på oppgavelinjen blinke når torrenten er ferdig nedlastet og/eller " -"vis sprettoppvarsel" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent ferdig nedlastet" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Nettverk Helsemonitor plugin\n" -"\n" -"Skrevet av Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Helse: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Instillinger for hendelseslogging" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Aktiver loggfiler" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Loggfiler" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Peer blokkert" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Sperre fullført" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Sperr nedlasting" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Bit fullført" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Lagring flyttet" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Trackeradvarsel" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Trackeralarm" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Trackersvar" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Trackerannonsering" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -#, fuzzy -msgid "Fastresume rejected error" -msgstr "Hurtigfortsett avviste feil" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -#, fuzzy -msgid "Peer ban error" -msgstr "Peer ban feil" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Hash feilet" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Filfeil" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Ugyldig forespørsel" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -#, fuzzy -msgid "Peer messages" -msgstr "Peer-beskjeder" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent fullført" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Velg hvilke hendelser som skal loggføres" - -#: plugins/EventLogging/__init__.py:22 -#, fuzzy -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Legger til fane med logg av valgte hendelser.\n" -"\n" -"Hendelsesbeskjeder kommer fra libtorrent-varsler.\n" -"Hvis du vil få disse strengene oversatt til ditt lokale,\n" -"må du rapportere problemet hos libtorrent, ikke Deluge.\n" -"\n" -"Angående loggfilene, disse lagres i en loggmappe\n" -"innenfor Deluge konfigurasjonsmappen. Hendelses-\n" -"beskjeder for spesifikke torrenter lagres til individuelle\n" -"loggfiler med samme navn som tilhørende .torrent-fil.\n" -"Hendelsesbeskjeder som ikke er spesifikke for en torrent\n" -"lagres til logger navngitt etter hendelsene.\n" -"(som peer_messages.log).\n" -"Hendelsesbeskjeder i loggfilene inkluderer også tidspunkt.\n" -"Brukeren er ansvarlig for å rengjøre loggen.\n" -"\n" -"Pr v0.2\n" -"Hendelser er nå beskjærte ved visning. Loggfilene er ikke det.\n" -"Nye hendelser er nå vist øverst.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Hendelseslogg" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "hendelsesmelding: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -#, fuzzy -msgid "Peer message" -msgstr "Peer-beskjed" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip-addresse: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "klient: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -#, fuzzy -msgid "piece index: " -msgstr "stykkeindeks: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "statuskode: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Antall ganger på rad: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "blokkindeks: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "peer-hastighet: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Den den ønskede fartsgrense per torrent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrent Ne_dlastingshastighet" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrent oppla_stingshastighet" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrent opplastingshastighet (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrent nedlastingshastighet (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Aktivitetsgraf for nettverksbruk plugin\n" -"\n" -"Skrevet av Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graf" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Framgang" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Det skjedde en feil ved åpning av filen." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Denne pluginen viser deg filene innenfor en torrent og lar deg prioritere og " -"velge hvilke du vil/ikke vil laste ned.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Filer" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Denne plugin tillater brukere å flytte en torrent til annen mappe uten å " -"måtte fjerne og legge til torrenten på nytt. Denne funksjonen finnes ved å " -"høyreklikke på torrenten.\n" -"Videre tillater denne brukeren å la ferdig nedlastede torrents bli flyttet " -"automatisk til annen mappe.\n" -"Merk: Filer kan foreløpig kun flyttes innad på samme partisjon." - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Flytt torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Bytt torrentkilde" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Velg en katalog å flytte filer til" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Du kan ikke flytte en torrent til en annen partisjon. Vennligst sjekk dine " -"innstillinger. Du kan heller ikke flytte en torrents filer til samme mappe " -"som de allerede ligger lagret, eller flytte en torrents filer før filene " -"faktisk har blitt opprettet." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Flytt ferdige nedlastinger til:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -#, fuzzy -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Denne plugin tillater brukere å legge til web seeds til sine torrents" - -#: plugins/WebSeed/__init__.py:51 -#, fuzzy -msgid "_Add Web Seed" -msgstr "_Legg til web seed" - -#: plugins/WebSeed/webseed.glade:7 -#, fuzzy -msgid "Add Web Seed" -msgstr "Legg til web seed" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Nedlastingsgrense:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Opplastingsgrense:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Aktive torrenter:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Opplastingstilkoblinger:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Maks forbindelser:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Instillinger for planleggeren" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "Grønn er øvre grenser, gul er nedre grenser, rød er stopp" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Grense satt til -1 tolkes som ubegrenset." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUI konfigurasjon" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Portnummer" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nytt passord" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Bekreft nytt passord" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Mal" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Knappestil" - -#: plugins/WebUi/__init__.py:208 -#, fuzzy -msgid "Cache Templates" -msgstr "Mellomlagringsmaler" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Tekst og bilder" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Kun bilder" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Kun tekst" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Bekreftet passord ulikt nytt passord\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "oversett noe" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Velg en url, torrent eller begge deler." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "ingen data." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "oppdatering må være større enn 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "Antall filer" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Om" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Legg til torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Utfør" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Oppdater automatisk:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Avansert" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Oppsett" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Data Dumping" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Slett nedlastede filer." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Deaktivèr" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Nedlastet" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Aktivèr" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Feil" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Estimat" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Innlogging" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Utlogging" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Neste Annonsering" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Av" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Passorder et ugyldig, prøv igjen" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pause alle" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Biter" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Kø ned" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Kø posisjon" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Kø opp" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Annonser på nytt" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Oppdater siden hver:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Fjern torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Fortsett alle" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Sett" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Set Tidsavbrudd" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Hastighet" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Start" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Bekreft" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrentliste" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Total Størrelse" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Trackerstatus" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Last opp torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Lastet opp" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekunder" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -#, fuzzy -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Feed vil bli hentet automatisk, basert på oppdateringsintervallet." - -#: plugins/FlexRSS/FlexRSS.glade:115 -#, fuzzy -msgid "Feed must be refreshed manually." -msgstr "Feed må oppfriskes manuelt." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Avslått" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Oppdateringsintervall" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Strømmer" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Type" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Strøm" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informasjon" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Mønstre" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Fra" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Sesong" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episode" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -#, fuzzy -msgid "Thru" -msgstr "Thru" - -#: plugins/FlexRSS/FlexRSS.glade:766 -#, fuzzy -msgid "History Restriction" -msgstr "Historierestriksjon" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Stemmer Ikke" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "År" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Måned" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Dag" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Leggtil torrent på toppen av køen." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Pause." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -#, fuzzy -msgid "Delete filter when matched." -msgstr "Slett filter når matchet." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Last Ned" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Erstatning" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Mønster" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -#, fuzzy -msgid "Link Rewriting" -msgstr "Lenkeomskriving" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -#, fuzzy -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Innhold vil bli lagret til Deluges standardmappe, Deluge vil be spørre om " -"mappe hvis ingen standardmappe er satt." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge standard" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Innhold vil bli lastet ned automatisk til spesifisert målmappe." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Velg:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Utdata" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtere" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Vis et FlexRSS-ikon i verktøylinjen til Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Vis knapp på verktøylinjen" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Grensesnitt" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -#, fuzzy -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Feed'er vil bli mottatt og analysert i egne tråder. Applikasjonen vil ikke " -"bli blokkert, men den kan være upålitelig." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Trådet (eksperimentell)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -#, fuzzy -msgid "Feed Retrieval" -msgstr "Feed-mottak" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domene" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Sti" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Verdi" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Informasjonskapsler" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Oppsett" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Behandle søkemotorer" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Navn:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Legg til en ny søkemotor ved å skrive inn Navn og URL. For Navn skriver du " -"inn navnet på søkemotoren som du skal bruke. For URL skriver du inn URL til " -"søkesiden. Det brukeren søker etter vil erstatte alle instanser av ${query} " -"i URL\n" -"Et eksempel, Google Søk, ville blitt:\n" -"Navn: Google\n" -"URL: http://www.google.com/search?=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Hjelp" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Søk etter torrent anonymt" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Søkestreng" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Velg en motor" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Administrer motorer" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Søk " diff --git a/po/nds.po b/po/nds.po deleted file mode 100644 index f6581954a..000000000 --- a/po/nds.po +++ /dev/null @@ -1,2388 +0,0 @@ -# German, Low translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-23 08:44+0000\n" -"Last-Translator: bmhm \n" -"Language-Team: German, Low \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Füge Torrent hinzu" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Tofögen" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Torrent wegmaken" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Wegdoon" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Entferne seedende Torrents" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Wiedermaken" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Paus" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Einstellungen" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugins" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Datei" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Torrent hinzufügen" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "URL_hinzufügen" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Vollständige Löschen" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Edit" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_gins" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Anzeige" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Toolbar" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Details" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Spalten" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Größe" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Status" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Seeders" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Peers" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Down Speed" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Up Speed" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Verbleibende Zeit" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Verfügbarkeit" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Share Ratio" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Hilfe" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Hilf diese Anwendung zu übersetzen" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Übersetze diese Anwendung" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Starte die erst-start Konfigurationshilfe" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Starte die Konfigurationshilfe" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Downloaded:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Uploaded:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Seeders:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Share Ratio:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Speed:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Peers:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "ETA:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Teile:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Verfügbarkeit:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistiken" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# Dateien" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Gesamtgröße:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Tracker Status:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Nächster Announce:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Name:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Pfad:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrent Info" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Details" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Lösche heruntergeladene Dateien" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Lösche .torrent Datei" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Zeige/Verberge" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Füge Torrent hinzu..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge Einstellungen" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Wähle einen Ordner" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Speicher alle Torrent Dateien in:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Speicher alle Downloads in:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Autoload" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Downloads" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Von:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Nach:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktiver Port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Aktiviere Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Port Mapping Protocol" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Peer Exchange" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Netzwerk" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Speed" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Konfiguration" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/nl.po b/po/nl.po deleted file mode 100644 index 503f06d49..000000000 --- a/po/nl.po +++ /dev/null @@ -1,2576 +0,0 @@ -# Dutch translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-25 17:07+0000\n" -"Last-Translator: mvoncken \n" -"Language-Team: Dutch \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Torrent toevoegen" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Toevoegen" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Torrent verwijderen" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Verwijder" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Verwijder seeding torrents" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Leegmaken" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Start of hervat torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Hervatten" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pauzeer torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pauzeren" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Torrent in wachtrij omhoog" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Naar boven" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Torrent in wachtrij omlaag" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Naar beneden" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Voorkeuren van Deluge wijzigen" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Instellingen" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugins" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Bestand" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Torrent toevoegen" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "_URL toevoegen" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Voltooide torrents wissen" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "B_ewerken" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_gins" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "Weerga_ve" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Knoppenbalk" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Details" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Kolommen" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Grootte" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Status" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Seeders" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Peers" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Downloadsnelheid" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Uploadsnelheid" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Resterende tijd" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Beschikbaarheid" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Deelverhouding" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Help" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Doneer aan de ontwikkeling van Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Doneer" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Homepage" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Website en forums" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Help dit programma te vertalen" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Vertaal dit programma..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "De configuratie wizard voor de eerste keer gestart" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Start de Configuratie wizard" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Gedownload:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Ge-upload:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Seeders:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Deelverhouding" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Snelheid:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Peers:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Resterende tijd:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Gedeelten:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Beschikbaarheid:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistieken" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# bestanden:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Totale grootte:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Tracker status:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Volgende aankondiging:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Naam:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Pad:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrent Info" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Details" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Weet u zeker dat u de geselecteerde torrent(s) uit " -"Deluge wilt verwijderen?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Gedownloade bestanden verwijderen" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr ".torrent-bestand verwijderen" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Weergeven/verbergen" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Torrent toevoegen" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Voltooide torrents verwijderen" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "Bestand _openen" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Alles selecteren" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Alles deselecteren" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Niet downloaden" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normaal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Hoog" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Hoogste" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge voeg tracker-lijsten samen" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent al gedetecteerd in Deluge, wil je de tracker-lijsten samenvoegen?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge-voorkeuren" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Vragen waar elke download moet worden opgeslagen" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Kies een map" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr ".torrent bestanden opslaan in:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Alle downloads opslaan in:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Downloadlocatie" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Laad alle .torrent bestanden in:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Automatisch laden" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Het aantal actieve torrents dat Deluge zal uitvoeren. Zet op -1 voor " -"onbeperkt." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maximum aantal gelijktijdig actieve torrents:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Schakel bestandsselectie van torrents in alvorens te laden" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Laat alleen zien als torrent meer dan 1 bestand heeft" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Geef voorrang aan eerste en laatste stukjes van bestanden in torrent" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Start torrent gepauseerd" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Volledige allocatie reserveert alle nodige ruimte voor de torrent op " -"voorhand en voorkomt schijffragmentatie" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Gebruik volledige allocatie" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Compacte allocatie reserveert ruimte alleen wanneer nodig" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Gebruik compacte allocatie" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Allocatie" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Downloads" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Let op - Wijzigingen aan deze instellingen worden pas de volgende keer " -"dat Deluge wordt gestart toegepast." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Vanaf:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Tot:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge zal elke keer automatisch een verschillende poort kiezen" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Willekeurige poorten" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Actieve poort testen" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Actieve poort:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Gedistributeerde hashtabel kan het aantal actieve verbindingen verbeteren." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Mainline DHT inschakelen" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Port Mapping Protocol" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Peer-uitwisseling" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Lokale Peer gevonden" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Netwerk extra's" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Binnenkomend:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Uitgeschakeld\n" -"Ingeschakeld\n" -"Geforceerd" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Uitgaand:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Geef voorkeur aan het encrypten van de gehele stroom" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Niveau:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Handschud\n" -"Complete stroom\n" -"Ofwel" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Encryptie" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Netwerk" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Torrents onderaan de wachtrij zetten als ze beginnen met seeden" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Zet nieuwe torrents in de wachtrij boven gereedzijnde" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" -"Stop met seeden van torrents als de deze deelverhouding wordt bereikt:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Verwijder automatisch torrents die de maximale deelverhouding hebben bereikt" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" -"Stop het seeden van torrents wanneer de seed-tijd de volgende waarde bereikt:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Aantal uren" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "Automatisch opschonen van torrents die de maximale seedtijd bereiken" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Seeden" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Seeding" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Maximum aantal connectie pogingen per seconde. Een hoge waarde kan " -"goedkopere routers laten vastlopen. Zet op -1 voor oneindig." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maximum connectie pogingen per seconde" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"De maximale upload plaatsen voor alle torrens. Gebruik -1 voor ongelimiteerd." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"De maximale uploadsnelheid voor alle torrents. Zet op -1 voor onbeperkt." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"De maximale downloadsnelheid voor alle torrents. Zet op -1 voor onbeperkt." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maximale downloadsnelheid (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" -"Het maximale aantal toegestane verbindingen. Zet op -1 voor onbeperkt." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maximaal aantal verbindingen:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maximale uploadsnelheid (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maximale upload plaatsen" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Het maximum aantal half-open verbindingen. Een hoge waarde kan sommige " -"goedkoper routers laten crashen. Zet op -1 voor ongelimiteerd." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maximum half-open verbindingen:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Globaal bandbreedtegebruik" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"De maximale upload plaatsen per torrens. Gebruik -1 voor ongelimiteerd" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Het maximum aantal verbindingen per torrent. Zet op -1 voor onbeperkt." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Bandbreedtegebruik per torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Bandbreedte" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Heeft invloed op normale bittorrent peers" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Peer proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Poort" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Geen\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 m. auth\n" -"HTTP\n" -"HTTP m. auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Wachtwoord" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Gebruikersnaam" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxytype" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Tracker proxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Web Seed Proxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxies" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Systeemvak-icoon inschakelen" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Naar systeemvak minimaliseren bij afsluiten" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Start in het systeemvak" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Door wachtwoord beschermd systeemvak" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Wachtwoord:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Systeemvak" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Gebruik de uitgebreide voortgangsbalk (gebruikt iets meer cpu en geheugen)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Gedetailleerde voortgangsbalk" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge zal automatisch onze servers controleren en melden wanneer er een " -"nieuwere versie verschenen is" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Laat het weten wanneer er nieuwe versies zijn" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Updates" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Help ons om Deluge te verbeteren door uw Python en PyGTK\n" -"versies, besturingssysteem en processor type te sturen. Geen\n" -"enkele andere informatie wordt verzonden." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Systeem informatie" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Overige" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Forceer Hercontrole" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "He_rvatten" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pauzeer" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "Torrent ve_rwijderen" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Tracker opties" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "Tracker vernie_uwen" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "Trackers b_ewerken" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Scrape Tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Wachtrij" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Bovenste" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "Om_hoog" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "Om_laag" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Onderste" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Open Bovenliggende Map" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "Deluge _tonen" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Hervat alles" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Pauzeer alles" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Download snelheidslimiet" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Upload snelheidslimiet" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "Af_sluiten" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Bewerk trackers" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Tracker wijzigen" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge bestandsselectie" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" -"Torrent zal niet worden gedistributeerd op het tracker-loos (DHT) netwerk" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Zet de prive vlag" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Eerste-opstart configuratie" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Deze wizard helpt je om Deluge naar je eigen wens in te stellen. Als je " -"nieuw bij Deluge bent, weet dan dat de meeste van Deluge zijn " -"functionaliteiten in de vorm van plugins komen, die je kan benaderen als je " -"op de Plugins knop drukt." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge maakt gebruik van een reeks van poorten om te luisteren naar " -"inkomende verbindingen. De standaard poorten voor bittorrent zijn 6881-6889, " -"echter de meeste internet providers blokkeren deze. Hierdoor wordt u " -"geadviseerd om een andere reeks, tussen 49152 en 65535, te kiezen. Daarnaast " -"kan Deluge ook automatisch een willekeurige poort selecteren." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Gebruik _willekeurige poorten" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Wilt u Deluge automatisch naar een voorgedefinieerde locatie laten " -"downloaden, of iedere keer de locatie opgeven?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Vraag waar elk bestand op te slaan" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Sla alle download op in: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Selecteer a.u.b. de upload snelheid van uw connectie, waarna we automatisch " -"een voorstel doen voor een iets lagere instelling" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maximum actieve torrents:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Uw upload snelheid:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Help ons Deluge te verbeteren door ons informatie te sturen over de door u " -"\n" -"gebruikte versies van Python en PyGTK, OS en processortype te\n" -"verzenden. Andere informatie wordt onder geen beding verzonden." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Niet mogelijk de browser vast te stellen. Controlleer of python-gnome2-" -"extras is geïnstalleerd of probeer de LD_LIBRARY_PATH en MOZILLA_FIVE_HOME " -"variabelen te plaatsen in /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Onbeperkt" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Geactiveerd" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Overig..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Download snelheid (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Upload snelheid (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge is vergrendeld" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge is beveiligd met een wachtwoord.\n" -"Type uw wachtwoord om het Deluge-venster te tonen," - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Oneindig" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Onbekend" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Naam" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Resterend" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Beschikbaar" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Verhouding" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Kies een directory om de torrent-bron naar te veranderen" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Verwijder de oude torrent bron?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "%s gepauzeerd" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "In wachtrij %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Er is een nieuwere versie van Deluge. Wilt u naar onze download site gaan?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Verbindingen" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Download" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Upload" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent Client" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Kies een downloadmap" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Er is een fout opgetreden bij het toevoegen van de torrent. Mogelijk is uw " -".torrent-bestand beschadigd." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Onbekende dubbele torrent fout." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Er is niet genoeg vrije ruimte om de download te voltooien." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Benodigde ruimte:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Beschikbare ruimte:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Torrent toevoegen vanaf URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Voer de URL in van te downloaden .torrent-bestand" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Waarschuwing - alle gedownloadde bestanden van deze torrent zullen worden " -"verwijderd!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Weet u zeker dat u alle torrents die seeding zijn, wilt verwijderen?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Wachtrij" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Controleren" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Bezig verbinding te maken" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Bezig met downloaden van metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Downloaden" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Voltooid" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Opzoeken" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes nodig" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Er is onvoldoende vrije ruimte om uw download te voltooien." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Aankondiging verzonden" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Aankondiging OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Waarschuwing" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP code" - -#: src/core.py:776 -msgid "times in a row" -msgstr "keer op een rij" - -#: src/core.py:788 -msgid "Warning" -msgstr "Opgelet" - -#: src/files.py:77 -msgid "Filename" -msgstr "Bestandsnaam" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioriteit" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Bestandsprioriteit kan alleen ingesteld worden wanneer volledige allocatie " -"wordt gebruikt.\n" -"Verander a.u.b. uw instellingen zo dat compacte allocatie wordt " -"uitgeschakeld, verwijder dan de torrent en voeg deze opnieuw toe." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Ingeschakeld" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge is vrije software. U mag het herdistribueren en/of \n" -"aanpassen onder de regels van de GNU General Public License, \n" -"gepubliceerd door de Free Software Foundation in\n" -"versie 2 van de licentie of (optioneel) elke latere versie.\n" -"Deluge wordt gedistribueerd met de hoop dat het nuttig is, echter\n" -"ZONDER ENIGE GARANTIE en ZONDER ENIGE WAARSCHUWING voor gebruik.\n" -"Lees de GNU General Public License voor meer informatie. U zou een\n" -"kopie gekregen moeten hebben bij Deluge. Als dit niet zo is schrijf dan\n" -"naar Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, \n" -"Boston, MA 02110-1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Kies een .torrent-bestand" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrentbestanden" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Alle bestanden" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Extern commando" - -#: src/common.py:207 -msgid "not found" -msgstr "niet gevonden" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Download en importeer verschillende ip blokkeerlijsten.\n" -"\n" -"Op dit moment kan deze plugin PeerGuardian (binair en tekst),\n" -"SafePeer en Emule lijsten aan. PeerGuardian lijsten in het 7zip formaat\n" -"worden niet ondersteund. Bestanden mogen als url's of lokale schijflocatie\n" -"worden opgegeven.\n" -"\n" -"Een pagina met links om blokkeerlijsten te downloaden, is te vinden op\n" -"de wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Tekst (zonder compressie)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP lijst (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeef Tekst (Zip)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Kon URL niet downloaden" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Kon blocklijst niet openen" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Verkeerd bestandstype of corrupt bestand." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Geïmporteerd" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP's" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blokkeerlijst" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "stuks" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Url van blokkeerlijst" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Download nieuwe blokkeringslijst elke" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dagen" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Bezig met laden en installeren van blokkeerlijst" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Bezig met importeren" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Voltooid" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Formaat fout in zipfile:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Ongeldig gzip bestand ontvangen, pas aub de Blocklist voorkeuren aan." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Foutieve leider" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Ongeldige magische code" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Ongeldige versie" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Stel de gewenste verhouding in voor een torrent" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Gewenste verhouding" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Niet ingesteld" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Niet ingesteld" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Gewenste verhouding" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Dit laat u de peers zien welke verbonden zijn met de torrent en laat hun IP " -"adres, land, gebruikte software, percentage gereed en de up- en download " -"snelheden zien.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP-adres" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Client" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Percentage voltooid" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrent maker" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Deze torrent wordt gecrëerd uit een enkel bestand" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Bestand:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Deze torrent wordt gecrëerd uit een map" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Map:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Bron:" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Sla torrent-bestand op als:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Laadt deze torrent in Deluge om te seeden" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Voeg nieuwe torrent toe aan wachtrij" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent-bestand" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackers" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Web Seeds" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Commentaren" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Auteur" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Stel Prive vlag in" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Hoe kleiner de stuk grootte, hoe efficienter de overdracht zal zijn, maar " -"het uiteindelijke \".torrent\" bestand zal groter zijn." - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Stukjes grootte:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Gevavanceerd" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Een torrent-maker plugin" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Nieuwe torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Nieuwe torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Maak nieuwe torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Bestand opslaan als..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "U moet een bron voor de torrent opgeven" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "U moet een bestand selecteren om de torrent op te slaan." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Torrent notificatie instellingen" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" -"Schakel gebeurtenis geluiden in (pygame benodigd. Niet beschikbaar voor " -"Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Activeer knipperend systeemvak-icoon" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Schakel popup notificatie in (python-notify is nodig, niet beschikbaar op " -"Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Laat het systeemvak-icoon knipperen en/of laat een notificatie zien wanneer " -"een torrent klaar is met downloaden" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent gereed" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Netwerk gezondheids monitor plugin\n" -"\n" -"Geschreven door Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Status: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Gebeurtenis log instellingen" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Zet log bestanden aan" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Log bestanden" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Peer geblokkeerd" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blok gereed" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Blok wordt gedownload" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Deel gereed" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Opslag locatie verplaatst" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Tracker waarschuwing" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Tracker melding" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Tracker antwoord" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Tracker aankondiging" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Snelhervatting afgewezen foutmelding" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Peer geblokkeerd foutmelding" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Hash mislukt foutmelding" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Bestandsfout" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Aanvraag ongeldig" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Peer berichten" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent klaar" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Selecteer de te registreren gebeurtenissen" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Voeg een tab toe met een log van de geselecteerde gebeurtenissen\n" -"\n" -"Gebeurtenis berichten komen van libtorrent waarschuwingen.\n" -"Als u deze strings wilt vertalen naar uw eigen taal,\n" -"moet u dit opnemen met libtorrent, niet met Deluge.\n" -"\n" -"Betreffende de log bestanden, de log's worden bewaard in een log\n" -"directory welke zich bevind in de Deluge configuratie directory.\n" -"Gebeurtenis berichten voor specifieke torrents worden bewaard in\n" -"individuele log bestanden met dezelfde naam als het bijbehorende\n" -" .torrent bestand. Gebeurtenis berichten niet specifiek gelinkt aan \n" -"een torrent worden bewaard in een log genaamd naar de\n" -"gebeurtenis (bijvoorbeeld: peer_messages.log)\n" -"Gebeurtenis berichten is de log bestanden hebben ook een tijdsindicatie.\n" -"De gebruiker is verantwoordelijk voor het schoonhouden van de logs.\n" -"\n" -"Vanaf v0.2\n" -"Gebeurtenissen worden nu afgebroken in het scherm. Log bestanden niet.\n" -"Nieuwe gebeurtenissen worden nu bovenin getoond.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Logboek" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "Gebeurtenis bericht: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Peer bericht" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip adres: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "client: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "Stuk index: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "statuscode: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Keer op een rij: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "blok index: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "peer snelheid: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Stel de maximale gewensde snelheid per torrent in." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrent_Download snelheid" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrent Upload _Snelheid" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrent upload snelheid (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrent download snelheid (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Netwerk activiteitsgrafiek plugin\n" -"\n" -"Geschreven door Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Grafiek" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Voortgang" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Er was een fout tijdens het starten van het bestand." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Deze plugin toont de bestanden in een torrent en geeft de mogelijkheid " -"prioriteiten toe te wijzen en te kiezen welke wel of niet gedownload moeten " -"worden\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Bestanden" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Deze plugin maakt het de gebruiker mogelijk om de torrent naar een andere " -"map te verplaatsen zonder te hoeven verwijderen en opnieuw toevoegen van de " -"torrent. Deze functie kan worden gevonden door met de rechtermuisknop te " -"klikken op een torrent.\n" -"Bovendien is de gebruiker in staat automatisch voltooide torrents te " -"verplaatst naar een andere map.\n" -"Opmerking: Bestanden kunnen momenteel alleen worden verplaatst binnen " -"dezelfde partitie" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Verplaats Torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Verander Torrent Bron" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Kies een map om bestanden naar te verplaatsen" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"U kan de torrent niet verplaatsen naar een andere partitie. Bekijk uw " -"instellingen hiervoor. Daarnaast kunt u torrent bestanden niet verplaatsen " -"naar dezelfde directory waar deze al waren opgeslagen of voordat de " -"bestanden enigsinds zijn aangemaakt." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Verplaats voltooide downloads naar:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Deze plugin staat gebruikers toe web seeds aan hun torrents toe te voegen" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Voeg Web Seed toe" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Web seed toevoegen" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Download limiet:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Upload limiet:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Active torrents:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Upload slots:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Maximum verbindingen:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Agenda instellingen" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "Groen is de hoge limiet, geel de lage limiet en rood is gestopt" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Een limiet van -1 betekent ongelimiteerd" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Web Interface Configuratie" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Poort Nummer" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nieuw Wachtwoord" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Nieuw Wachtwoord (nog een keer)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Template" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Knop Weergave" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Cache Templates" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Tekst en ikoon" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Alleen een ikoon" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Alleen tekst" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Het bevestigde wachtwoord is ongelijk aan het eerste wachtwoord.\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "dummy string op te testen of de vertalingen werken." - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Kies een url of een torrent-bestand, niet biede." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "geen gegevens." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "\"Ververs Iedere\" moet groter zijn dan 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "Aantal bestanden" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Over" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Torrent toevoegen" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Toepassen" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Verversen" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Besch" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Configuratie" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Data Dump" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Verwijder de gedownloadde bestanden." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Deactiveren" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Gedownload" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Activeren" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Fout" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Resterende tijd" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Inloggen" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Uitloggen" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Volgende aankondiging" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Uit" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Het wachtwoord is ongelding, probeer het nog een keer." - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pauzeer alles" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Stukken" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Omlaag in wachtrij" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Wachtrij positie" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Omhoog in wachtrij" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Opnieuw aankondigen" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Ververs iedere:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Verwijder torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Alles activeren" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Instellen" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Stel timeout in" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Snelheid" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Start" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Ok" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrent lijst" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Totale omvang" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Tracker status" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Torrent bestand uploaden" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Geupload" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "seconden" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"Feed zal automatisch opgehaald worden, afhankelijk van de update interval." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Feed moet handmatig ververst worden." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Uitgeschakeld" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Vernieuw interval" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feeds" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Type" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informatie" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Patronen" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Van" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Seizoen" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Aflevering" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Tot" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Geschiedenis beperking" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Geen match" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Jaar" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Maand" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Dag" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Torrent invoegen aan het begin van de wachtrij." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Zet status naar pauze." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Verwijder filter wanneer die overeen komt." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Download" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Vervanging" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Patroon" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Link herschrijving" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Inhoud zal opgeslagen worden in Deluge's standaard map, of een vraag zal " -"verschijnen als niets is ingesteld." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge standaard" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Inhoud zal automatisch worden gedownload naar de opgegeven map." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Kies:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Uitvoer" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filters" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Toon een FlexRSS ikoon in de toolbar van deluge." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Toon knop op toolbar." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interface" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Feeds worden opgehaald in hun eigen draad. De applicatie zal niet " -"geblokkeerd worden, maar kan onbetrouwbaar zijn." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Threaded (experimenteel)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Ophalen van feeds" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domein" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Pad" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Waarde" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Configuratie" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Beheer Zoekplugins" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Naam:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Voeg een nieuwe zoekmachine toe door een naam en een url in te voeren. Voer " -"bij Naam de naam van de zoekmachine in. Bij URL geef je de url van de " -"zoekpagina. De\n" -"zoekopdracht van de gebruiker zal ${query} in de url vervangen.\n" -"Bijvoorbeeld, een zoekopdracht door Google zou worden:\n" -"Naam: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Help" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Anoniem zoeken naar torrents" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Zoekterm" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Zoekplugin kiezen" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Beheer zoekmachines" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Zoek " diff --git a/po/pl.po b/po/pl.po deleted file mode 100644 index 5f6b2c3b1..000000000 --- a/po/pl.po +++ /dev/null @@ -1,2585 +0,0 @@ -# Polish translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: Michał Kaliszka \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-24 17:28+0000\n" -"Last-Translator: Łukasz Wyszyński \n" -"Language-Team: Polish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Dodaj plik torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Dodaj" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Usuń Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Usuń" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Wyczyść rozsiewane torrenty" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Wyczyść" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Rozpocznij lub wznów pobieranie" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Wznów" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Wstrzymaj torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Wstrzymaj" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Przenieś o jedno miejsce w kolejce w górę" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "W górę" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Przenieś o jedno miejsce w kolejce w dół" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "W dół" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Zmień ustawienia Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Opcje" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Wtyczki" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Plik" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Dodaj torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Dodaj _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Usuń zakończone" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Edycja" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Wty_czki" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Widok" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Pasek narzędzi" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Szczegóły" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Kolumny" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Rozmiar" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Stan" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Rozsiewających" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Uczestnicy" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Szybk. pobierania" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Szybk. wysyłania" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Pozostały czas" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Dostępność" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Ratio" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Pomoc" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Wesprzyj rozwój Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Dofinansuj" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Strona domowa" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Społeczność" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Pomóż w tłumaczeniu tego programu" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "Prze_tłumacz ten program..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Uruchamia kreatora pierwszej konfiguracji" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "U_ruchom kreatora konfiguracji" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Pobrano:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Wysłano:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Rozsiewających:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Udział w %:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Prędkość:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Pobierających:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Do końca:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Części:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Dostępność:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statystyki" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Liczba plików:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Rozmiar:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Status trackera:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Następna zapowiedź:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nazwa:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Ścieżka:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Informacje o torrencie" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Szczegóły" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Czy jesteś pewien, że chcesz usunąć zaznaczony " -"torrent(y)" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Skasuj pobrane pliki" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Usuń plik .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Pokaż/Ukryj" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Dodaj plik .torrent" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Usuń zakończone" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Otwórz plik" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Zaznacz wszystko" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Odznacz wszystko" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Nie pobieraj" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normalny" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Wysoki" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Najwyższy" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Łączenie listy trakerów" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "Torrent jest już w Deluge, czy chcesz połączyć listy tracerów?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Ustawienia Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Pytaj, gdzie zapisać każdy plik" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Wybierz folder" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Przechowuj wszystkie pliki torrentów w:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Przechowuj wszystkie pobierane pliki w:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Lokacja pobranych plików" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Automatycznie ładuj wszystkie torrenty w:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Ładowanie automatyczne" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Liczba aktywnych torrentów jakie Deluge uruchomi. Ustaw -1 by nie było " -"limitu." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maksymalna liczba aktywnych torrentów:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Uruchom wybieranie plików przed rozpoczęciem pobierania" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Pokazuj tylko jeśli torrent ma więcej niż 1 plik" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Pobieraj najpierw pierwsze i ostatnie części plików" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Torrenty startują jako wstrzymane" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrenty" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Tryb pełnego przydziału alokuje cały obszar dysku potrzebny na pliki, co " -"zapobiega fragmentacji dysku" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Pełny przydział miejsca" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Tryb oszczędny alokuje miejsce według potrzeb" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Oszczędny przydział miejsca" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Przydział" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Pobierane" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"UWAGA - zmiany poniższych ustawień zostaną wdrożone dopiero po ponownym " -"uruchomieniu Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Od:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Do:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge za każdym razem wybierze automatycznie inny port." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Losowe porty" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Testuj port" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktywny port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Rozproszona tablica skrótów (DHT) może pomóc zwiększyć ilość aktywnych " -"połączeń." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Włącz DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Uniwersalne Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "Protokół mapowania portów NAT" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -#, fuzzy -msgid "Peer Exchange" -msgstr "Wymiana partnerów" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Lokalne wyszukiwanie partnerów" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Dodatkowe opcje" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Przychodzące:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Wyłączone\n" -"Włączone\n" -"Wymuszone" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Wychodzące:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Preferuj szyfrowanie całego strumienia" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Poziom:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Negocjacja połączenia\n" -"Cały strumień\n" -"Obydwa" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Szyfrowanie" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Sieć" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Ustawiaj ukończone torrenty na spodzie kolejki" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Ustawiaj nowe torrenty powyżej ukończonych" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Zatrzymaj rozsiewanie torrenta, gdy jego ratio osiagnie:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Automatycznie czyść torrenty, które osiągną maksymalne ratio" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Zaprzestań seedować torenty kiedy czas ich seedowania osiągnie:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Liczba godzin" - -#: glade/preferences_dialog.glade:1142 -#, fuzzy -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Automatycznie usuwaj torrenty, które osiągnęły maksymalny czas rozsiewania" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Rozsiewanie" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Rozsiewanie" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Maksymalna liczba prób połączeń na sekundę. Za wysoka wartość może zawiesić " -"niektóre tanie routery. Ustaw -1 dla nieograniczonej liczby połączeń." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maksymalna liczba prób połączeń na sekundę:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Maksymalna ilość połączeń wychodzących dla wszystkich plików torrent. " -"Wartość -1 oznacza brak ograniczeń." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maksymalna prędkość wysyłania danych dla wszystkich torrentów. Wartość -1 " -"oznacza brak ograniczeń." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maksymalna prędkość pobierania dla wszystkich plików torrent. Wartość -1 " -"oznacza brak ograniczeń." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maksymalna prędkość pobierania (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" -"Maksymalna ilość możliwych połączeń. Wartość -1 oznacza brak ograniczeń." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maksymalna liczba połączeń:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maksymalna prędkość wysyłania (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maksymalna ilość połączeń wychodzących:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Maksymalna liczba półotwartych połączeń. Za wysoka wartość może zawiesić " -"niektóre tanie routery. Ustaw -1 dla nieograniczonej liczby połączeń." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maksymalna liczba półotwartych połączeń:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Globalny przydział przepustowości łącza" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Maksymalna ilość połączeń wychodzących przypadająca na pojedynczy plik " -"torrent. Wartość -1 oznacza brak ograniczeń." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Maksymalna liczba połączeń na torrent. Wartość -1 oznacza brak ograniczeń." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Przydział przepustowości na każdy torrent z osobna" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Przepustowość" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -#, fuzzy -msgid "Affects regular bittorrent peers" -msgstr "Dotyczy przeciętnych peerów sieci bittorrent" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Pośrednik dla peerów" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Serwer" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Żaden\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 (wymagający autoryzacji)\n" -"HTTP\n" -"HTTP (wymagający autoryzacji)" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Hasło" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Nazwa użytkownika" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Rodzaj pośrednika" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Pośrednik dla peerów" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Pośrednik trackera" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Pośrednik trackera" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Pośrednik DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Pośrednik DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Pośrednik trybu Web Seed" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Pośrednik trybu Web Seed" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Pośrednicy" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Pokaż ikonę na tacce systemowej" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Po zamknięciu minimalizuj do ikony na tacce systemowej" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Uruchamiaj w tacce systemowej" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Zabezpiecz tackę hasłem" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Hasło:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Tacka systemowa" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Szczegółowy pasek postępu (nieco większe zużycie CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Szczegółowy pasek postępu" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge będzie sprawdzał nasze serwery i poinformuje Cię jeśli pojawi się " -"nowa wersja" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Informuj o nowych wydaniach" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Aktualizacje" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Pomóż nam ulepszać Deluge wysyłając nam numer wersji\n" -"Pythona, PyGTK, systemu oraz typ procesora. Żadne inne\n" -"informacje nie są wysyłane." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Informacje o systemie" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Inne" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Wymuś ponowne sprawdzenie" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Wz_nów" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Wstrzymaj" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Usuń torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "Opcje _trackera" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Aktualizuj informacje o trackerze" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Edycja trackerów" - -#: glade/torrent_menu.glade:138 -#, fuzzy -msgid "_Scrape Tracker" -msgstr "_Kłopotliwy Tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Kolejka" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Najwyżej" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "W _górę" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "W _dół" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "N_ajniżej" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Otwórz folder zawierający" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Pokaż Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "Wz_nów wszystkie" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Wstrzymaj wszystkie" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Limit prędkości pobierania" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Limit prędkości wysyłania" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "Wy_jdź" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Edycja trackerów" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Edycja trackerów" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Wybór plików" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrent nie będzie dostępny w beztrackerowej sieci (DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Ustaw jako prywatny" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Konfiguracja przy pierwszym uruchomieniu" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Kreator ten pomoże Ci dostosować Deluge do własnych potrzeb. Jeśli używasz " -"programu po raz pierwszy, to zwróć uwagę na fakt, że większość z jego " -"możliwości i funkcji dostarczanych jest w postaci wtyczek, do których dostęp " -"uzyskuje się po kliknięciu na Wtyczki w menu Edycja lub pasku narzędzi." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge musi mieć określony zakres portów, na których będzie oczekiwał " -"przychodzących połączeń. Domyślnymi portami dla sieci bittorrent są 6881-" -"6889, jednakże większość dostawców blokuje ten zakres, więc zachęcamy do " -"wybrania innych, najlepiej z zakresu 49152-65535. Ewentualnie można nakazać " -"Deluge losowanie portów." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Użyj _losowych portów" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Wolisz, żeby Deluge automatycznie pobierał pliki do ustalonego miejsca, czy " -"raczej wolisz za każdym razem określać położenie?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Pytaj gdzie zapisać każdy plik" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Zapisuj wszystkie pobrania w: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Proszę podać prędkość wysyłania danych Twego połączenia, która pozwoli " -"automatycznie zasugerować pozostałe opcje poniżej" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maksymalna ilość aktywnych torrentów:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Prędkosć wysyłania danych Twego łącza" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Pomóż nam ulepszyć Deluge. Wystarczy, że wyślesz nam twoją wersję Pythona i " -"PyGTK,\n" -" typ systemu operacyjnego i procesora. Nic po za tymi informacjami\n" -" nie będzie wysłane." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Nie można uruchomić przeglądarki. Upewnij się, że masz zainstalowaną paczkę " -"python-gnome2-extras lub spróbuj ustawić zmienne środowiska LD_LIBRARY_PATH " -"oraz MOZILLA_FIVE_HOME na /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Bez limitu" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktywne" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Inna..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Prędkość pobierania (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Prędkość wysyłania (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge jest zablokowany" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge jest chroniony hasłem.\n" -"Aby pokazać Deluge, wpisz hasło." - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Nie do określenia" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Nieznany" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nazwa" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Pozostało" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Dost." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Ratio" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Wybierz katalog, na który chcesz zmienić źródło torrenta" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Usunąć stare źródło torrenta?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Wstrzymano %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "W kolejce %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "Pojawiła się nowa wersja Deluge. Czy chcesz odwiedzić naszą stronę?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Połączeń" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Szybk. pobierania" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Szybk. wysyłania" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge - klient sieci Bittorrent" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Wskaż katalog, w którym zapisywane będą dane" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Wystąpił błąd podczas dodawania torrentu. Możliwe, że twój plik jest " -"uszkodzony." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Nieznany błąd powielenia torrenta." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Brak wystarczającej ilości wolnego miejsca na dysku by dokończyć ściąganie." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Miejsce potrzebne:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Miejsce dostępne:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Dodaj plik .torrent z URLa" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Wpisz URL prowadzący do pliku .torrent" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Uwaga - wszystkie pliki ściągnięte dla tego torrenta zostaną skasowane!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Jesteś pewien, że chcesz usunąć wszystkie rozsiewające torrenty?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "W kolejce" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Sprawdzanie" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Łączę" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Ściąganie danych meta" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Pobieranie" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Ukończono" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Alokowanie" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "potrzebnych bajtów" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" -"Nie ma wystarczającej ilości wolnego miejsca na zakończenie pobierania." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Zapowiedź wysłana" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Zapowiedź OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Uwaga" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "kod HTTP" - -#: src/core.py:776 -msgid "times in a row" -msgstr "razy z rzędu" - -#: src/core.py:788 -msgid "Warning" -msgstr "Ostrzeżenie" - -#: src/files.py:77 -msgid "Filename" -msgstr "Nazwa pliku" - -#: src/files.py:82 -msgid "Priority" -msgstr "Priorytet" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Priorytet pliku może być ustawiony tylko po wybraniu pełnej alokacji. Zmień " -"ustawienia, po czym usuń i ponownie dodaj ten torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Wtyczka" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Aktywne" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge jest wolnym oprogramowaniem; możesz go\n" -"rozprowadzać dalej i/lub modyfikować na warunkach Powszechnej\n" -"Licencji Publicznej GNU, wydanej przez Fundację Wolnego\n" -"Oprogramowania - według wersji 2-giej tej Licencji lub którejś\n" -"z późniejszych wersji.\n" -"Niniejszy program rozpowszechniany jest z nadzieją, iż będzie on\n" -"użyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej\n" -"gwarancji PRZYDATNOŚCI HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH\n" -"ZASTOSOWAŃ. W celu uzyskania bliższych informacji - Powszechna\n" -"Licencja Publiczna GNU.\n" -"Z pewnością wraz z niniejszym programem otrzymałeś też egzemplarz\n" -"Powszechnej Licencji Publicznej GNU (GNU General Public License);\n" -"jeśli nie - napisz do Free Software Foundation, Inc., 51 Franklin\n" -"St, Fifth Floor, Boston, MA 02110-1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Wybierz plik .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Pliki .torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Wszystkie pliki" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Polecenie zewnętrzne" - -#: src/common.py:207 -msgid "not found" -msgstr "nie znaleziono" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Pobierz i zaimportuj przeróżne czarne listy IP.\n" -"\n" -"W chwili obecnej, ta wtyczka potrafi obsłużyć listy PeerGuardiana\n" -"(binarne i tekstowe), SafePeera i Emule. Pliki peerguardiana w\n" -"formacie 7zipa nie są obsługiwane. Pliki mogą być określone w\n" -"postaci URLa, lub lokacji w lokalnym systemie plików.\n" -"\n" -"Strona, ze spisem innych stron zawierających czarne listy jest\n" -"dostępna na wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "Tekst PeerGuardian (Nieskompresowany)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Lista Emule IP (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "Tekst SafePeer (Zip)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Nie można pobrać adresu URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Nie można otworzyć pliku z czarną listą" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Nieprawidłowy typ pliku lub uszkodzony plik czarnej listy." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Zaimportowano" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "adresów IP" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Lista blokowania" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "wpisy" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL czarnej listy" - -#: plugins/BlocklistImport/ui.py:52 -#, fuzzy -msgid "Download new blocklist every" -msgstr "Pobierz nową listę blokowanych co" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dni" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Ładowanie i instalacja czarnej listy" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importowanie" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Ukończono" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Otrzymano wyjątek formatowania dla pliku zip:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Oczekiwano pliku gzip, ale nie otrzymano go, lub plik jest uszkodzony. Zmień " -"swoje ustawienia Czarnej Listy." - -#: plugins/BlocklistImport/peerguardian.py:32 -#, fuzzy -msgid "Invalid leader" -msgstr "Błędny prowadnik" - -#: plugins/BlocklistImport/peerguardian.py:36 -#, fuzzy -msgid "Invalid magic code" -msgstr "Niepoprawny kod magiczny" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Nieprawidłowa wersja" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Ustaw pożądany wskaźnik wymiany dla pliku .torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Żądane Ratio" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Nie ustawiono" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Nie ustawiono" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Żądane ratio" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Pokazuje klientów ściągających dany torrent, pokazuje ich IP, kraj, wersję " -"klienta, kompletność pliku oraz prędkość ściągania i wysyłania.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Adres IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klient" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Procent ukończenia" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Kreator torrentów" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Ten torrent będzie stworzony z pojedynczego pliku" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Plik:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Ten plik .torrent zostanie utworzony z katalogu" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Katalog:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Źródło" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Zapisz torrent jako:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Załaduj ten plik torrent do Deluge aby rozpocząć rozsiewanie" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Dodaj nowe pobieranie do kolejki" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Plikt .torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackery" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -#, fuzzy -msgid "Web Seeds" -msgstr "Tryb Web Seed" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Komentarze" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Ustaw jako prywatny" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Im mniejsze będą rozmiary części, tym wydajniejszy będzie transfer, ale " -"właściwy plik .torrent będzie większy" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Rozmiar części:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Zaawansowane" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Wtyczka tworzenia plików .torrent" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Nowy plik .torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Nowy plik .torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Stwórz nowy plik .torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Zapisz plik jako..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Musisz wybrać źródło dla pliku .torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Musisz wybrać plik, aby zapisać plik .torrent" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Ustawienia powiadamiania" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" -"Włącz sygnalizację dźwiękiem wydarzenia (wymaga pygame, niedostępne pod " -"Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Włącz migającą ikonkę w trayu" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Włącz wyskakujące okienka (wymaga python-notify, niedostępne w Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "Migaj ikonką / wyświetl popup kiedy torrent zostanie pobrany" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Zakończono pobieranie torrenta" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Wtyczka Monitora Kondycji Sieci\n" -"\n" -"Napisana przez Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Kondycja: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Ustawienia logowania zdarzeń" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Włącz dziennik" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Dziennik" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Pobierający zablokowany" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blok skończony" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Blok pobierany" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Część ukończona" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Zasób przeniesiony" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Ostrzeżenie trackera" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Alarm trackera" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Odpowiedź trackera" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Zapowiedź trackera" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Błąd szybkiego wznawiania" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Błąd blokowania pobierającego" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Błąd nieudanego hasha" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Błąd pliku" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Błędne żądanie" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Wiadomości uczestników" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent ukończony" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Wybierz zdarzenia do logowania" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Dodaje zakładkę z dziennikiem wybranych zdarzeń.\n" -"\n" -"Zdarzenia pochodzą z alertów libtorrenta.\n" -"Jeżeli chcesz przetłumaczyć te wiadomości na Polski,\n" -"zgłoś tą sugestie do twórców libtorrenta, nie deluge.\n" -"\n" -"Odnośnie plików dziennika: są one przechowywanie w\n" -"katalogu w którym jest przechowywana konfiguracja deluge\n" -"Zdarzenia powiązane z poszczególnymi torrentami są przechowywane\n" -"w dziennikach o tej samej nazwie co nazwa pliku .torrent\n" -"Zdarzenia nie powiązane z żadnych szczególnym torrentem\n" -"są zachowywane do dzienników o nazwach zdażeń (np.\n" -"peer_messages.log).\n" -"Wiadomości zdarzeń w plikach dziennika są zapisywane z datą\n" -"Użytkownik jest odpowiedzialny za czyszczenie logów.\n" -"\n" -"Od wersji 0.2:\n" -"Treść zdarzenia są przycinanie przy wyświetlaniu, jednak w plikach dziennika " -"tak nie jest.\n" -"Nowe zdarzenia są wyświetlane na szczycie listy.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Dziennik zdarzeń" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "treść zdarzenia: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Wiadomość klienta" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "adres ip: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "klient: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "numer części: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "kod statusu: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Razy z żędu " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "numer bloku: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "prędkość pobierającego " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Ustaw żądany limit prędkości na torrent" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Prędkość _pobierania torrenta" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Prędkość _wysyłania torrenta" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Prędkość wysyłania torrenta (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Prędkość pobierania torrenta (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Wtyczka Wykresu Aktywności Sieci\n" -"\n" -"Napisana przez: Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Wykres" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Postęp" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Wystąpił błąd przy próbie uruchomienia pliku." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Ta wtyczka pokazuje jakie pliki znajdują się wewnątrz torrenta i pozwala Ci " -"ustawić dla nich priorytety oraz określić, które pliki chcesz pobrać, a " -"które nie.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Pliki" - -#: plugins/MoveTorrent/__init__.py:22 -#, fuzzy -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Ten plugin umożliwia przenoszenie torrentów do innego katalogu bez " -"konieczności usuwania i ponownego dodawania torrenta. Funkcję tę można " -"odnaleźć po prawym kliknięciu na torrencie.\n" -"Ponadto, plugin umożliwia automatyczne przenoszenie pobranych torrentów do " -"innego katalogu.\n" -"Uwaga: Obecnie torrenty mogą być przenoszone tylko w obrębie tej samej " -"partycji" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Przenieś torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "Zmień źródło torrenta" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Wybierz katalog, do którego przenieść pliki" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Nie możesz przenieść torrenta do innej partycji. Proszę sprawdź swe " -"ustawienia. Dodatkowo, nie możesz przenieść plików torrentów do tego samego " -"katalogu w którym jest on już przechowywany czy też przenieść plików " -"torrentów przed tym jak jakikolwiek plik zostanie utworzony." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Przenieś zakończone pobrania do:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "Ta wtyczka pozwala użytkownikom dodać Web Seedy do swych torrentów" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Dodaj Web Seed" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Dodaj Web Seed" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Limit pobierania:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Limit wysyłania:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Aktywne torrenty:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Sloty dla wysyłania:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Maksymalna liczba połączeń:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Ustawienia harmonogramu" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Zielony oznacza wysoki limit, żółty - niski, czerwony oznacza - wstrzymano" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Jeżeli limit jest ustawiony na -1, to wtedy nie ma ograniczeń." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Konfiguracja interfejsu sieciowego" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Port numer" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nowe hasło" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Nowe hasło(powtórz)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Szablon" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Styl przycisków" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Przechowuj szablony" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Tekst i grafika" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Tylko grafika" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Tylko tekst" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Potwierdzono hasło <> Nowe hasło\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "przetłumacz coś" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Wybierz adres lub torrent, nie oba." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "brak danych." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "odświeżanie musi być > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# Plików" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "O programie" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Dodaj torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Zastosuj" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Automatyczne odświeżanie:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Dost." - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Ustawienia" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Zrzut danych" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Usuń pobrane pliki" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Wyłącz" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Pobrano" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Włącz" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Błąd" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Pozostało" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Zaloguj się" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Wyloguj się" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Następna zapowiedź" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Wyłączony" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Hasło jest niepoprawne, spróbuj ponownie" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Wstrzymaj wszystko" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Fragmentów" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Przenieś o jedno miejsce w kolejce w dół" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Pozycja w kolejce" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Przenieś o jedno miejsce w kolejce w górę" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Ponownie zgłoś zapowiedź" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Odśwież stronę co:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Usuń torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Wznów wszystkie" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Ustaw" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Ustaw czas aktywności" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Prędkość" - -#: plugins/WebUi/scripts/template_strings.py:53 -#, fuzzy -msgid "Start" -msgstr "Start" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Wyślij" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Lista torrentów" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Całkowity rozmiar" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Stan trackera" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Wyślij torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Wysłane" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekund" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"Kanał RSS będzie pobierany automatycznie, zależnie od czasu odświeżania." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Kanał RSS musi być odświeżany ręcznie." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Wyłączone" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Czas odświeżania" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "Adres URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Kanały" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Typ" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Kanał RSS" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informacje" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Wzory" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Od" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Sezon" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Odcinek" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Przez" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Restrykcje historii" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Nie pasuje" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Rok" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Miesiąc" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Dzień" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Wstaw torrent na górę kolejki" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Ustaw stan jako wstrzymany." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Usuń filtr gdy znaleziono pasujące." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Pobieranie" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Zamiana" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Wzór" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Zamiana odnośników" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Zawartość będzie zapisana w domyślnym katalogu Deluge, lub pojawi się " -"wybrania ścieżki, jeżeli nie ustawiono żadnego." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Domyślne Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Zawartość będzie automatycznie pobierana do wybranego katalogu." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Wybierz:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Wyjście" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtry" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Pokaż ikonę FlexRSS na pasku narzędzi Deluge." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Pokaż przycisk na pasku narzędzi." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interfejs" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Kanały RSS będą pobierane i odczytywane w swoich własnych wątkach. Aplikacja " -"nie będzie zablokowana, ale może stać się niestabilna." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Wielowątkowe (eksperymentalne)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Pobieranie kanałów RSS" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domena" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Ścieżka" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Wartość" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Ciasteczka" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Konfiguracja" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Zarządzaj wtyczkami" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nazwa:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Dodaj nową wyszukiwarkę podając Nazwę i URL. Dla Nazwy wybierz najlepiej " -"nazwę serwisu wykorzystywaną do wyszukiwania torrentów. Jako URL, wpisz " -"adres prowadzący do strony wyszukiwania. Żądanie użytkownika zastąpi pole " -"${query} w URLu.\n" -"Na przykład, wyszukiwanie z pomocą google powinno wyglądać następująco:\n" -"Nazwa: Google\n" -"URL: http://www.google.pl/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Pomoc" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Anonimowo szukaj torrentów" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Wyszukiwany tekst" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Wybierz silnik" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Zarządzaj silnikami" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Szukaj " diff --git a/po/pms.po b/po/pms.po deleted file mode 100644 index e24bce5a4..000000000 --- a/po/pms.po +++ /dev/null @@ -1,2388 +0,0 @@ -# Piemontese translation for deluge -# Copyright (c) 2008 Rosetta Contributors and Canonical Ltd 2008 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2008. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-19 22:37+0000\n" -"Last-Translator: Triton \n" -"Language-Team: Piemontese \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Pulida" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/pt.po b/po/pt.po deleted file mode 100644 index 8286b121d..000000000 --- a/po/pt.po +++ /dev/null @@ -1,2579 +0,0 @@ -# Portuguese translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-11 08:03+0000\n" -"Last-Translator: João Santos \n" -"Language-Team: Portuguese \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Adicionar Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Adicionar" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Remover Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Remover" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Limpar Torrents Já Completos" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Limpar" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Iniciar ou Continuar Torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Continuar" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Parar Torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pausa" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Mover o torrent para cima na fila" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Subir" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Mover o torrent para baixo na fila" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Descer" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Modificar preferências" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Preferências..." - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugins" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Ficheiro" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Adicionar Torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Adicionar _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "Limpar _Completos" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Editar" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_gins" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Ver" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Barra de Ferramentas" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detalhes" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Colunas" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Tamanho" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Estado" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Sementes" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Pares" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Velocidade de Recepção" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Velocidade de Envio" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Tempo Restante" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Disponibilidade" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Rácio de Partilha" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Ajuda" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Doar para o Desenvolvimento do Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Doar" - -#: glade/delugegtk.glade:458 -#, fuzzy -msgid "_Homepage" -msgstr "Página _Web" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Comunidade" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Ajude a traduzir esta aplicação" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Traduza Esta Aplicação..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Executa o assistente de configuração inicial" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Executar o assistente de configuração" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Transferidos:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Enviados:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Sementes:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Rácio de Partilha" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Velocidade:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Pares:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Tempo Restante Estimado:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Partes:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Disponibilidade" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Estatísticas" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# de ficheiros:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Tamanho Total:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Estado do Tracker:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Próximo anúncio:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nome:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Caminho:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Informação do Torrent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detalhes" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Têm a certeza que deseja remover o(s) torrent(s) " -"seleccionado(s)?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Apagar ficheiros recebidos" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Eliminar o ficheiro .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Mostrar/Ocultar" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Adicionar Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Limpar Concluídos" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "Abrir Ficheir_o" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Seleccionar Todos" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Desfazer Todas Selecções" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Não transferir" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Elevado" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Mais elevado" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Juntar Listas do Tracker Deluge" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent já detectado no Deluge, gostaria de juntar as listas de tracker?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Preferências do Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Perguntar onde gravar cada download" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Seleccione Uma Pasta" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Guardar todos os ficheiros .torrent em:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Guardar todos os ficheiros recebidos em:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Localização dos ficheiros recebidos" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Auto-Carregar todos os ficheiros em:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Auto-Carregar:" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"O número de torrents activos que o Deluge irá ter. (-1 para ilimitados)" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Máximo de torrents activos simultâneamente:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Activar selecção de ficheiros para torrents antes de carregar" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Mostrar o torrent apenas se este tiver mais do que 1 ficheiro" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Dar prioridade ao primeiro e último pedaço dos ficheiros no torrent" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Iniciar os torrents em estado parado" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"O alocamento Completo reserva todo o espaço em disco necessário que o " -"torrent necessita e previne a fragmentação do Disco Rigído" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Alocamento Completo" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Alocamento compacto aloca apenas o espaço conforme necessário." - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Alocamento Compacto" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Alocamento" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Recepções" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Nota - Alterações a estas definições irão ser apenas aplicadas da próxima " -"vez que o Deluge é iniciado." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "De:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Para:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" -"O Deluge irá escolher automaticamente uma porta diferente todas as vezes." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Portas aleatórias" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Testar Porta Activa" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Porta Activa:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Hash Table distribuída pode melhorar a quantidade de ligações activas." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Activar Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Protocolo de Mapeamento de Portas" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Troca de Pares" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Descoberta de Pares Locais" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Extras de Rede" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Entrada" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Desabilitado\n" -"Habilitado\n" -"Forçado" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Saida:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "De preferência, cifrar toda a ligação" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Nível:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Cumprimento\n" -"Stream Completo\n" -"Ambos" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Cifragem" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Rede" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Mover torrents para o fundo quando ficarem completos" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Adicionar novos torrents acima dos terminados" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Parar de semear os torrents quando o seu rácio atingir:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Limpar automaticamente os torrents que atinjam o rácio máximo de partilha" - -#: glade/preferences_dialog.glade:1105 -#, fuzzy -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Parar o semeio de torrents quando atinjam o tempo máximo de semeio." - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Número de horas" - -#: glade/preferences_dialog.glade:1142 -#, fuzzy -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Automaticamente apagar torrents que cheguem ao tempo máximo de partilha" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "A Semear" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "A semear" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"O número máximo de tentativas de ligação por segundo. Um valor elevado pode " -"mandar abaixo alguns routers baratos. (-1 para ilimitado)" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Número Máximo de Tentativas de Ligação por Segundo:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "O número máximo de envios para os torrents. (-1 para ilimitados)" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Velocidade máxima de envio para todos os torrents. (-1 para ilimitada)" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Velocidade máxima de recepção para todos os torrents. (-1 para ilimitada)" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Velocidade máxica de recepção (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Número máximo de ligações permitidas. (-1 para ilimitado)" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Número Máximo de Ligações:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Velocidade Máxima de Envio (KB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Número Máximo de Envios:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"O máximo de ligações meio abertas. Um valor elevado poderá mandar abaixo " -"routers mais baratos. Coloque -1 para ligações ilimitadas." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Número Maximo de Ligações Meias-abertas:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Uso de Banda Global" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "O número máximo de envios por torrent. (-1 para ilimitado)" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "O número máximo de ligações por torrent. (-1 para ilimitadas)" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Uso de Banda Por Torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Largura de Banda" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Afecta clientes bittorrent normais" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Proxy de utilizador" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Porta" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Servidor" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Nenhum\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 c/ Autenticação\n" -"HTTP\n" -"HTTP c/ Autenticação" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Senha" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Nome de utilizador" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Tipo de proxy" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Proxy de utilizador" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Proxy do tracker" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Proxy do tracker" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Proxy DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Proxy DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Proxy das Sementes Web" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Proxy das Sementes Web" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxies" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Activar o ícone na barra de sistema" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimizar para a barra de sistema" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Iniciar na barra de sistema" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" -"Proteger icone da barra de sistema \n" -" com palavra passe" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Palavra passe:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Barra de Sistema" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Usar a barra de progresso avançada (usa ligeiramente mais CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Barra de Progresso Detalhada" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "Deluge vai verificar se existem actualizações" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Ser informado sobre novas versões" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Actualizações" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Ajude-nos a melhorar o Deluge enviando-nos as suas versões Python e PyGTK\n" -" e os tipos de SO e processadores. Não é enviada qualquer outra informação" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Informação do Sistema" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Outro" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "Forçar Reverificação" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Re_sumir" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Parar" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Remover Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "Opções de _Tracker" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "Act_ualizar Tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Editar Trackers" - -#: glade/torrent_menu.glade:138 -#, fuzzy -msgid "_Scrape Tracker" -msgstr "_Scrape Tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Fila" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Topo" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "S_ubir" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Descer" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Fundo" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Abrir Pasta" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Mostrar Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Continuar Tudo" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Parar Todos" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Limite de Velocidade de Transferência" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Limite de Velocidade de Envio" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Sair" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Editar Trackers" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Edição de Trackers" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Selecionador de ficheiros do Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "O torrent não vai ser distribuído na rede DHT" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Definir como privado" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Configuração Inicial" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Este assistente irá ajudá-lo a configurar o Deluge à sua ligação. Se é a sua " -"primeira utilização, note que a maioria dos recursos e funcionalidades do " -"Deluge podem ser acedidas através de plugins, que podem ser acedidos atráves " -"da opção \"Plugins\" no menu \"Editar\"." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"É necessário definir, para o deluge, uma gama de portas que este usa para " -"ficar à escuta de conexões provenientes do exterior. As portas por defeito " -"para bittorrent são 6881-6889, contudo, a maioria dos ISP's bloqueiam essas " -"portas, tornando aconselhável o uso de outras portas, entre 49152 e 65535. " -"Como alternativa, é possivel que o Deluge faça a selecção das portas de " -"forma automática." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Usar_Portas Aleatórias" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Gostaria que o Deluge descarregasse automaticamente para uma localização pré-" -"definida, ou prefere especificar uma localização cada vez que fizer um " -"download?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Perguntar sempre aonde guardar cada ficheiro" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Guardar todas as transferências em: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Por favor seleccione a velocidade de envio da sua ligação, que será " -"utilizada para fazer sugestões automáticas para as configurações abaixo" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Número máximo de torrents activos:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "A sua capacidade de envio:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Ajude-nos a melhorar o Deluge enviando-nos as suas versões do Python e do " -"Pygtk,\n" -" dos sistemas operativos utilizados e do tipo de processadores utilizados. " -"Mais nenhuma\n" -" informação é enviada" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Não foi possível determinar o browser. Verifique se tem o pacote python-" -"gnome2-extras instalado ou tente definir as suas variáveis de ambiente " -"LD_LIBRARY_PATH e MOZILLA_FIVE_HOME para /usr/lib/fireofx" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Ilimitado" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Activado" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Outro(a)..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Velocidade de Recepção (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Velocidade de Envio (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "O Deluge está bloqueado" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"O Deluge está protegido por uma palavra passe.\n" -"Para mostrar a janela do Deluge, introduza a sua palavra passe" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infinito" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Desconhecido" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nome" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "TEC" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Dispo." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Rácio" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Escolha a pasta" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Eliminar a fonte antiga do torrent?" - -#: src/interface.py:953 -#, fuzzy, python-format -msgid "Paused %s" -msgstr "Parado(s) %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Existe uma nova versão do Deluge. Deseja ser reencaminhado para o site de " -"download?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Ligações" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Recepção" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Envio" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Cliente de Bittorrent Deluge" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Escolha um directório para recepção" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Ocorreu um erro ao adicionar o torrent. Possivelmente o ficheiro .torrent " -"está corrupto." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Erro desconhecido de torrente duplicado." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Não existe espaço suficiente no disco para completar o download." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Espaço Necessário:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Espaço Disponível:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Adicionar torrent do URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Introduza o URL do ficheiro .torrent" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Aviso - Todos os ficheiros recebidos deste torrent vão ser apagados!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Têm a certeza que deseja remover todos os torrentes já completos?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Na Fila" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "A Verificar" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "A estabelecer ligação" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "A transferir Metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "A transferir" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Concluído" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "A alocar" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes necessários" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Não existe espaço suficiente em disco para completar o download." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Anúncio enviado" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Anúncio OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Alerta" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "Codigo HTTP" - -#: src/core.py:776 -msgid "times in a row" -msgstr "vezes numa coluna" - -#: src/core.py:788 -msgid "Warning" -msgstr "Aviso" - -#: src/files.py:77 -msgid "Filename" -msgstr "Nome do ficheiro" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioridade" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"A prioridade de ficheiros só poderá ser definida quando é usada a alocação " -"total.\n" -"Por favor altere as preferências para desactivar a alocação compacta, remova " -"o torrent e volte a adiciona-lo." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Activado" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"O Deluge é software livre, poderá ser redistribuido e/ou modifica-lo " -"mediante os termos da GNU General Public\n" -"License como publicado pela Free Software Foundation,\n" -"ou pela versão 2 da licença, ou (mediante a sua opção) outra\n" -"qualquer versão subsequente. O Deluge é distribuido na esperança\n" -"de ser útil, mas SEM QUALQUER GARANTIA, incluindo a ausência da garantia " -"implícita de COMERCIALIZAÇÂO ou \n" -"ADEQUAÇÂO para um propósito ESPECÍFICO. Consulte a licença GNU General\n" -"Public License para maiores detalhes. Deverá ter recebido uma cópia da " -"licença GNU General Public License\n" -"com o Deluge, mas se não for esse o caso, escreva para Free Software " -"Foundation\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Escolher um ficheiro .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Ficheiros Torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Todos os ficheiros" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Comando externo" - -#: src/common.py:207 -msgid "not found" -msgstr "não encontrado" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Descarregar e importar várias listas de IP's bloqueados.\n" -"\n" -"Actualmente este plugin pode lidar com PeerGuardian (binário e texto),\n" -"SafePeer e listas do Emule. Os ficheiros PeerGuardian de formato 7zip não " -"são\n" -"suportados. Os Ficheiros podem ser especificados como URLs ou localizações " -"no\n" -"sistema local\n" -"\n" -"Uma página com apontadores para descarregar listagens está disponível na " -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Text (Não comprimido)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Lista de IP's do Emule (Gzip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "Texto SafePeer (Zipado)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Não foi possível descarregar o endereço" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Não foi possível abrir o ficheiro da lista de Bloqueios" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Tipo de ficheiro errado ou corrompido." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importado" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "LIsta de Bloqueados" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "entradas" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Endereço de Lista de Bloqueados" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Descarregar nova lista de blocos a cada" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dias" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "A carregar e a instalar a Lista de Bloqueados" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "A Importar" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Concluído" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Obtida uma excepção de formato do arquivo zip:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Era esperado um ficheiro gzip, mas não foi recebido, ou é possível que o " -"ficheiro esteja corrumpido. Por favor edite a suas preferências da lista de " -"bloqueios." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Invalid leader" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Código mágico inválido" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Versão inválida" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Insira o rácio desejado para um torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "Rácio _Desejado" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Não Definido" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Não Definido" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Rácio Desejado" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Isto mostra quem está associado a cada torrent, mostrando o seu ip, país, " -"cliente, percentagem de obtenção e velocidades de\n" -"envio e recepção.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Endereço IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Cliente" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Percentagem Completa" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Criador de Torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Este torrent será criado de um único ficheiro" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Ficheiro:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Este torrente será criado de um directorio" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Pasta:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Origem" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Guardar Torrent Como:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Carrega o torrent no Deluge para semear" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Adicione um novo torrent à lista de espera" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Ficheiro de Torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackers" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -#, fuzzy -msgid "Web Seeds" -msgstr "Sementes Web" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Comentários" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Definir como Privado" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Quanto menor o tamanho de cada uma das partes, maior será a eficiência na " -"processo de transferência, mas o ficheiro \".torrent\" será maior" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Tamanho da parte:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Avançado" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Plugin para criação de torrents" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Novo Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Novo Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Criar Novo Torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Guardar ficheiro como..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Têm de seleccionar uma fonte para o torrent." - -#: plugins/TorrentCreator/__init__.py:128 -#, fuzzy -msgid "You must select a file to save the torrent as." -msgstr "Deve seleccionar um ficheiro para salvar o torrent." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Preferencias de Notificação do Torrent" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Activar eventos sonoros (necessita pygame, não desponível em Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Activar o piscar do icone de notificação" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Activar notificações via popup (necessita python-notify, não desponível em " -"Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Fazer o icone da barra de tarefas piscar quando o download do torrent acabar " -"e/ou notificar-me por popup" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent completo" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Plugin Monitor de Saúde da Rede\n" -"\n" -"Desenvolvido por Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Saúde: Ok]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Preferências de Registo de Eventos" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Activar ficheiros de registo" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Ficheiros de Registo" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Par bloqueado" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Bloqueio terminado" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Transferência de bloco" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Parte terminada" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -#, fuzzy -msgid "Storage moved" -msgstr "Armazenamento movido" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Aviso do Tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Alerta do Tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Resposta do Tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Anunciar no tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Erro de Rejeição de Resumo Rápido" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Erro ao banir par" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Falha na verificação do Hash" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Erro de ficheiro" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Pedido inválido" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Mensagens do par" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent terminado" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Seleccione eventos a registar" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Adiciona uma aba com o registo de eventos seleccionados.\n" -"\n" -"As mensagens de eventos vêm dos alertas do libtorrent.\n" -"Se quer esses textos traduzidos para a sua lingua,\n" -"deverá tratar da situação com o libtorrent, não com o deluge.\n" -"\n" -"Sobre os ficheiros de registo, estes são gravados num directório\n" -"de registos dentro do directório de configuração do deluge.\n" -"Mensagens de eventos para torrents especificos são gravados\n" -"em ficheiros individuais nomeados apartir do ficheiro .torrent \n" -"associado. Mensagens não especificas a um torrent são\n" -"guardadas em registos nomeados apartir dos eventos\n" -"(ex peer_messages.log).\n" -"Mensagens no ficheiro de registo também incluem um \"timestamp\".\n" -"O utilizador é responsável por limpar os registos.\n" -"\n" -"Apartir da v0.2\n" -"Eventos exibidos são truncados, os ficheiros não.\n" -"Novos eventos são exibidos no topo.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Registo de Eventos" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "Mensagem de Eventos: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Mensagem de Par" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "Endereço IP: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "Cliente: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "Index da Parte: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "Código de estado: " - -#: plugins/EventLogging/tab_log.py:152 -#, fuzzy -msgid "Times in a row: " -msgstr "Vezes numa linha: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "Índice de blocos: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "velocidade do par " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Ajustar o limite de velocidade para cada torrent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Velocidade de Transferência _de Torrent" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Velocidade de envio dos torrent_s" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Velocidade de Envio (KiB/s:)" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Velocidade de Recepção (KiB/s:)" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Plugin de Grafico de Actividade da Rede\n" -"Escrito por Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Gráfico" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Evolução" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Ocorreu um erro na abertura do ficheiro" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Este plugin mostra-lhe os ficheiros contidos no torrent, permitindo definir " -"prioridades e excluir ficheiros que não queiramos fazer download\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Ficheiros" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Mover torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Mudar Fonte do Torrent" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Escolha um directório para onde mover os ficheiros" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Não poderá mover o torrent para uma partição diferente. Por favor verifique " -"as suas preferências. Não poderá mudar os ficheiros de torrent para o mesmo " -"directório onde já eles estão, ou mover ficheiros de torrents antes de " -"qualquer um destes tenham sido criados." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Mover ficheiros completamente recebidos para:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Este plugin permite aos utilizadores adicionar sementes 'da rede' aos seus " -"torrents" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Adicionar Semente 'da Rede'" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Adicionar Semente 'da Rede'" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Limite de download:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Limite de upload:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Torrents activos:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Slots de Upload:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Máximo de Conecções:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Definições da Agenda" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"A verde estão os limites máximos, a amarelo os mínimos e a vermelho estão " -"parados" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Se o limite está definido para -1, é ilimitado" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Configuração da Interface Web" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Número da Porta" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nova Palavra-passe" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Nova Palavra-passe (confirmação)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Modelo" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Estilo do Botão" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Arquivo de Modelos" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Texto e imagem" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Apenas imagem" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Apenas Texto" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Palavra-passe Confirmada <> Palavra-passe\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "traduzir alguma coisa" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Escolha uma url ou um torrent, não ambos." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "sem dados." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "atualização deve ser > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# de Ficheiros" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Sobre" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Adicionar torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Aplicar" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Auto actualizar:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Disp" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Configuração" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Informações de saída" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Remover ficheiros recebidos." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Desactivado" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Recebidos" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Activar" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Erro" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Tempo Estimado" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Autenticar" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Sair" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Próximo Anúncio" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Desactivar" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Palavra-passe inválida, tente novamente" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Parar todos" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Partes" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Descer na Lista" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Posição na fila" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Subir na Lista" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Re-anúnciar" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Actualizar página a cada:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Remover torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Continuar todos" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Seleccionar" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Definir tempo de esgotamento" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Velocidade" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Iniciar" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Enviar" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Lista de torrents" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Tamanho Total" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Estado do Tracker" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Enviar torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Enviado" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "segundos" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"A feed será recebida automaticamente, de acordo com intervalo de " -"actualização." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "As feeds devem ser actualizadas manualmente" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Desactivado" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Intervalo de Actualização" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feeds" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tipo" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informação" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Padrões" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "De" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Temporada" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episódio" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Através" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Restrição Histórica" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Não coincide" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Ano" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Mês" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Dia" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Teste" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Inserir torrent no topo da fila" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Definir estado como parado" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Apagar filtro quando correspondido" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Download" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Substituição" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Padrão" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Reescrever Ligação" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"O conteúdo será gravado no directório por definição do Deluge ou um será " -"pedido se este não estiver definido." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Padrão Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" -"O conteúdo será automaticamente transferido para o directório especificado" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Escolha:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Saída" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtros" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Mostrar um ícone FlexRss na barra de ferramentas do Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Mostar botão na barra de ferramentas" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interface" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"As feeds serão recebidas e processadas nos seus próprios treads. A aplicação " -"não irá bloquear, mas pode não ser fiável." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Threaded (experimental)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Recuperar Feed" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domínio" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Caminho" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Valor" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Configuração" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Gerir 'Plugins' de Procura" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nome:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Adicione um mecanismo de busca inserindo um nome e uma URL. Para nome, " -"coloque o nome do mecanismo de busca a ser usado. Para URL, coloque o " -"endereço da página de busca. Os parâmetros de busca do usuário irão " -"substituir qualquer ocorrência de ${query} na URL.\n" -"Por exemplo, uma pesquisa no Google seria:\n" -"Nome: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Ajuda" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Procurar por torrents anonimamente" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Termos de Pesquisa" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Escolha um Motor de Pesquisa" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Gerir Motores de Pesquisa" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Pesquisar " diff --git a/po/pt_BR.po b/po/pt_BR.po deleted file mode 100644 index 65281185c..000000000 --- a/po/pt_BR.po +++ /dev/null @@ -1,2581 +0,0 @@ -# Portuguese (Brazil) translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-05 19:19+0000\n" -"Last-Translator: Daniel Demarco \n" -"Language-Team: Portuguese (Brazil) \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Adicionar Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Adicionar" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Remover Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Remover" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Remover Torrents Semeados" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Limpar" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Iniciar ou Continuar Torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Continuar" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pausar Torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pausar" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Adiantar na fila" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Acima" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Atrasar na fila" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Abaixo" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Alterar Preferências do Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Preferências" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Plugins" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "A_rquivo" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Adicionar Torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Adicionar _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Limpar Concluídos" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Editar" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Plu_gins" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Ver" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "Barra de _Ferramentas" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detalhes" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Colunas" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Tamanho" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Estado" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Semeadores" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Peers" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Velocidade de Down" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Velocidade de Up" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Tempo Restante" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Disponibilidade" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Taxa de Compartilhamento" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "A_juda" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Doar e ajudar o Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "Faça uma _Doação" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Página Inicial" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "P_erguntas Freqüentes" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Comunidade" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Ajude a traduzir esta aplicação" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Traduzir Esta Aplicação..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Abre o assistente de configuração inicial" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Abrir Assistente de Configuração" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Baixado:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Enviado:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Seeders:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Taxa de Compartilhamento:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Velocidade:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Peers:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Tempo estimado:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Partes:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Disponibilidade:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Estatísticas" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "n° de arquivos:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Tamanho Total:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Rastreador:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Estado do Rastreador:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Próximo Anúncio:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nome:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Caminho:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Informação do Torrent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detalhes" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Você tem certeza de que deseja remover o(s) " -"torrent(s) selecionado(s) do Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Apagar arquivos baixados" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Apagar arquivo .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Mostrar/Ocultar" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Adicionar um Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Limpar Concluídos" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Abrir Arquivo" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Selecionar Todos" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Desmarcar Todos" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Não baixar" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Padrão" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Prioritário" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Mais Prioritário" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge Unir Listas de Trackers" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrent já detectado no Deluge, gostaria de unir as listas de trackers?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Preferências do Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Perguntar onde salvar cada download" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Selecione Uma Pasta" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Armazenar todos os arquivos torrent em:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Armazenar todos os downloads em:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Localização do Download" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Autocarregar todos os arquivos torrent em:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Autocarregar" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"O número de torrents ativos que o Deluge vai trabalhar. Ajuste para -1 para " -"ilimitado." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Máximo de torrents ativos simultaneamente:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Permitir selecionar arquivos dos torrents antes de carregá-los." - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Mostrar somente torrents com mais de 1 arquivo" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Priorizar primeira e última parte dos arquivos no torrent" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Iniciar torrents em estado pausado" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Alocação total pré-aloca todo o espaço necessário para o torrent e previne a " -"fragmentação do disco" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Usar Alocação Total" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Alocação compacta somente aloca espaço conforme necessário" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Usar Alocação Compacta" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Alocação" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Downloads" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Atenção - As modificações nestas configurações serão aplicadas somente na " -"próxima vez que Deluge for reiniciado." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "De:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Para:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" -"O Deluge irá automaticamente escolher uma porta diferente para utilizar a " -"cada vez." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Portas Aleatórias" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Testar Porta Ativa" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Porta Ativa:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"A tabela de hash distribuída (THD) pode melhorar a quantidade de conexões " -"ativas." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Habilitar Rede THD" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "THD" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Plug and Play Universal" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "Protocolo de Mapeamento de Porta NAT" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Troca de Pares" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Descoberta de Pares Locais" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Extras de Rede" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Entrada:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Desabilitado\n" -"Habilitado\n" -"Forçado" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Saída:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Preferir encriptar o fluxo por inteiro" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Nível:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Handshake\n" -"Full Stream\n" -"Either" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Criptografia" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Rede" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Mover os torrents para o fim da fila quando começarem a semear" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Enfileirar novos torrents acima dos completados" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" -"Parar de semear torrents quando sua razão de compartilhamento alcança:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Automaticamente limpar torrents que alcancem a razão de compartilhamento " -"máxima" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Parar de semear torrents quando o tempo de semeamento atingir:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Número de horas" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Limpar automaticamente torrents que atinjam o tempo máximo de semeamento" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Semeando" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Semeando" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Número máximo de tentativas de conexão por segundo. Um valor alto pode " -"travar roteadores mais simples. Configurar com -1 para ilimitado." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Máximo de Tentativas de Conexão por Segundo:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Número máximo de slots de upload para todos os torrents. Defina -1 para " -"ilimitado." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"A velocidade máxima de upload para todos os torrents. Defina -1 para " -"ilimitado." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"A velocidade máxima de download para todos os torrents. Defina -1 para " -"ilimitado." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Velocidade Máxima de Download (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "O número máximo de conexões permitido. Defina -1 para ilimitado." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Máximo de Conexões:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Velocidade Máxima de Upload (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Máximo de slots de Upload:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"O máximo de conexões semi-abertas. Um valor muito alto pode travar alguns " -"roteadores fracos. Coloque -1 para ilimitado." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Máximo de Conexões Semi-Abertas:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Uso da Banda Global" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "O máximo de slots de upload por torrent. Defina -1 para ilimitado." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "O número máximo de conexões por torrent. Defina -1 para ilimitado." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Uso da Banda po Torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Largura de Banda" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Afeta pontos comuns de bittorrent" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Proxy de Ponto" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Porta" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Servidor" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Nenhum\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 c/ Autenticação\n" -"HTTP\n" -"HTTP c/ Autenticação" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Senha" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Nome do Usuário" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Tipo de Proxy" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Proxy do Ponto" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Proxy do Rastreador" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Proxy do Rastreador" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Proxy THD" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "THD Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Proxy da Semente da Internet" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Proxy da Semente da Internet" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxies" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Habilitar ícone na bandeja" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimizar para a bandeja ao fechar" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Iniciar na bandeja" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Proteger ícone com senha" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Senha:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Área de Notificação" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Usar barra de progresso avançada (usa pouco mais CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Barra de Progresso Detalhada" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge checará nossos servidores e dirá se uma nova versão foi lançada." - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Seja alertado sobre novos lançamentos" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Atualizações" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Nos ajude a melhorar o Deluge enviando a versão do Python e\n" -"PyGTK, Sistema Operacional e tipo de processador. Nenhuma\n" -"outra informação será enviada." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Informações do Sistema" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Outro" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Forçar Re-checagem" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "_Continuar" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pausar" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Remover Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Opções do Rastreador" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Atualizar Rastreador" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Editar Rastreadores" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Editar Rastreadores" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Fila" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Topo" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "A_cima" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "A_baixo" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Fundo" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Abrir pasta do arquivo" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Mostrar Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Retomar Todos" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Pausar Todos" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Limite da Velocidade de Download" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Limite da Velocidade de Upload" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "Sai_r" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Editar Rastreadores" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Editando Rastreador" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Seleção de Arquivos do Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrent não vai ser distribuido na rede sem rastreador (THD)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Definir flag privada" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Configuração da primeira inicialização" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Este assistente irá ajuda-lo a ajustar Deluge ao seu gosto. Se você é novo " -"ao Deluge, por favor note que a maioria das funcionalidades e dos recursos " -"do Deluge vem na forma de plugins, que podem ser acessados clicando em " -"Plugins no menu Editar ou na barra de ferramentas." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"O Deluge necessita de um intervalo de portas para que ele possa aceitar " -"conexões de entrada. As portas padrão para o bittorrent são 6881-6889, " -"porém, muitos provedores de serviços bloqueiam estas portas, então sugerimos " -"que escolha outras, entre 49152 e 65535. Alternativamente, você pode querer " -"que o Deluge automaticamente escolha portas aleatórias para você." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Usa_R Portas Aleatórias" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Você quer que o Deluge baixe automaticamente para um local predefinido, ou " -"gostaria de especificar o local do download a cada vez?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Perguntar onde salvar cada arquivo" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Armazenar todos os downloads em: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Por favor, selecione a velocidade de upload da sua conexão, a qual usaremos " -"para automaticamente fazer sugestões para as configurações abaixo." - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Máximo de torrents ativos:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Sua Velocidade de Upload" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Ajude-nos a melhorar o Deluge enviando suas versões do Python e PyGTK\n" -"Sistema Operacional e tipo de processador. Nenhuma outra\n" -"informação é enviada." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Não foi possível encontrar o navegador. Assegure-se de ter o pacote python-" -"gnome2-extras instalado, ou tente atribuir às variáveis de ambiente " -"LD_LIBRARY_PATH e MOZILLA_FIVE_HOME o valor /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Ilimitado" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Ativado" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Outro..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Velocidade de download (KiB/s)" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Velocidade de upload (KiB/s)" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge está trancado" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge está protegido por senha.\n" -"Para ver a janela do Deluge, entre com sua senha" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infinito" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Desconhecido" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nome" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Tempo Estimado" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Disp." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Razão" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Escolha um local para trocar onde o torrent foi salvo" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Deletar os arquivos do local prévio?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Pausado %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Na fila %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Existe uma nova versão do Deluge. Deseja abrir a nossa página de download?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Conexões" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "THD" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Download" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Upload" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Cliente Bittorrent Deluge" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Escolha um diretório para download" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Ocorreu um erro ao adicionar o torrent. É possível que o arquivo .torrent " -"esteja corrompido." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Erro desconhecido de torrent duplicado." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Não há espaço livre em disco suficiente para completar o seu download." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Espaço Necessário:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Espaço Disponível:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Adicionar torrente de uma URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Coloque a URL do .torrent para download" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Atenção - todos os arquivos recebidos deste torrent serão excluídos!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" -"Você têm certeza de que deseja remover todos seus torrents semeadores?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Na Fila" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Verificando" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Conectando" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Baixando metainformações" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Baixando" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Concluído" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Alocando" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes necessários" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Não há espaço em disco suficiente para completar seu download." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Anúncio enviado" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Anúncio OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Aviso" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "Código HTTP" - -#: src/core.py:776 -msgid "times in a row" -msgstr "vezes seguidas" - -#: src/core.py:788 -msgid "Warning" -msgstr "Alerta" - -#: src/files.py:77 -msgid "Filename" -msgstr "Nome do arquivo" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioridade" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"A prioridade do arquivo só pode ser definida quando se está usando alocação " -"completa.\n" -"Por favor altere as preferências para desabilitar a alocação compacta, " -"depois remova e re-adicione este torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Plugin" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Habilitado" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge é software livre. Você pode redistribuir e/ou\n" -"modificá-lo sob os termos da Licença Pública\n" -" GNU como publicado pela Free Software Foundation,\n" -"tanto pela versão 2 da Licença, quanto (sua opção) qualquer\n" -"outra versão mais nova. Deluge é distribuído na esperança\n" -"de que será útil, mas SEM GARANTIA, mesmo pela garantia \n" -"implicada da MERCANTILIDADE ou BEM-ESTAR\n" -"POR UM PROPÓSITO PARTICULAR. Veja a Licença Pública GNU\n" -"para mais detalhes. Você deveria ter recebido uma cópia da\n" -"Licença GNU junto com o Deluge, mas, se não recebeu, escreva\n" -"para a Free Software Foundation,\n" -"Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Escolha um arquivo .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Arquivos Torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Todos os arquivos" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Comando externo" - -#: src/common.py:207 -msgid "not found" -msgstr "não encontrado" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Faz o download e importa várias listas de bloqueio de IP\n" -"\n" -"Atualmente este plugin pode gerenciar listas PeerGuardian (binário e " -"texto),\n" -"SafePeer e Emule. Arquivos PeerGuardian no formato 7zip não são\n" -"suportados. Arquivos podem ser especificados como URLs ou localização no\n" -"sistema de arquivos local.\n" -"\n" -"Uma página com apontamentos para download de listas de bloqueio está " -"disponível\n" -"no wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Texto (não compactado)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Lista de IP do Emule (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Texto (Zipado)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Não pôde baixar a URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Não foi possível abrir arquivo de lista de bloqueios" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Tipo de arquivo errado ou arquivo blocklist corrompido." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importada" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Lista de bloqueios" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "entradas" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL da lista de bloqueios" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Baixar nova lista de bloqueio (blocklist) a cada" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dias" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Carregando e instalando lista de bloqueios" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importando" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Terminado" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Obtida uma excepção de formato do arquivo zip:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Era esperado um arquivo gzip, mas não foi recebido, ou foi recebido um " -"arquivo corrompido. Por favor edite a suas preferências da lista de " -"bloqueios." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Líder inválido" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Código mágico inválido" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Versão inválida" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Defina a proporção desejada para um torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Proporção Desejada" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Não Definido" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Não definido" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Proporção Desejada" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Isso mostra os peers associados com cada torrent e mostra o ip, país, " -"cliente, percentagem completa e velocidades de download e upload.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Endereço IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Cliente" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Porcentagem concluída" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Criador de Torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Este torrent será feito a partir de um único arquivo" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Arquivo:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Este torrent será feito a partir de um diretório" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Pasta:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Fonte" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Salvar arquivo Torrent como:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Carregar esse torrent no Deluge para semear" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Adicionar novo torrent à fila" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Arquivo Torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackers" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Sementes da Web" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Comentários" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Marcar como privado" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Quanto menores os pedaços, mais eficientes as transferências serão, mas o " -"arquivo \".torrent\" será maior" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Tamanho da parte:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Avançado" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Um plugin para criar torrents" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Novo Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Novo Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Criar novo torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Salvar arquivo como..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Você deve selecionar uma fonte para o torrent" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Você deve selecionar um arquivo para salvar o torrent como." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Preferências de Notificação do Torrent" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Habilitar eventos de som (requer pygame, não disponível em Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Permitir que o ícone da bandeja pisque" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Ativar notificação por popup (requer python-notify, não disponível para " -"Windows)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Piscar o ícone da bandeja quando concluído um download e/ou mostrar " -"notificação" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent completo" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Plugin do monitor do estado da rede\n" -"\n" -"Escrito por Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Estado: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Preferências do Log de Eventos" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Ativar arquivos de log" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Arquivos de log" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Colega bloqueado" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Bloco finalizado" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Bloquear download" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Parte completa" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Armazenamento movido" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Aviso do rastreador" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Alerta do rastreador" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Resposta do rastreador" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Anúncio do rastreador" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Erro de rejeição do fastresume" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Erro ao banir Peer" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Falha na verificação do Hash" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Erro de arquivo" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Solicitação inválida" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Mensagens do Peer" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent finalizado" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Selecione eventos para logar" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Adiciona uma aba com o registo de eventos selecionados.\n" -"\n" -"As mensagens de eventos vêm dos alertas do libtorrent.\n" -"Se quer esses textos traduzidos para a sua lingua,\n" -"deverá tratar da situação com o libtorrent, não com o deluge.\n" -"\n" -"Sobre os ficheiros de registo, estes são gravados num diretório\n" -"de registos dentro do diretório de configuração do deluge.\n" -"Mensagens de eventos para torrents especificos são gravados\n" -"em ficheiros individuais nomeados apartir do ficheiro .torrent \n" -"associado. Mensagens não especificas a um torrent são\n" -"guardadas em registos nomeados apartir dos eventos\n" -"(ex peer_messages.log).\n" -"Mensagens no ficheiro de registo também incluem um \"timestamp\".\n" -"O utilizador é responsável por limpar os registos.\n" -"\n" -"Apartir da v0.2\n" -"Eventos exibidos são truncados, os ficheiros não.\n" -"Novos eventos são exibidos no topo.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Log de Eventos" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "mensagem do evento: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Mensagem do Peer" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "endereço ip: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "cliente: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "indexação de parte: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "código de status: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Vezes seguidas: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "indexação do bloco: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "velocidade do peer: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Defina o limite de velocidade por torrent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Velocidade de _Download do Torrent" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "_Velocidade de Upload do Torrent" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Velocidade de Upload do Torrent (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Velocidade de Download do Torrent (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Plugin Gráfico de Atividade da Rede\n" -"\n" -"Escrito por Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Gráfico" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progresso" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Ocorreu um erro ao tentar carregar o arquivo." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Este plugin lhe mostra os arquivos dentro de um torrent e permite que você " -"defina prioridades para eles e escolha quais quer ou não baixar.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Arquivos" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Este plugin permite ao usuário mover o torrent a um local diferente sem ter " -"que remover e readicionar o torrent. Esta característica pode ser " -"encontranda clicando com o botão direito sobre um torrent.\n" -"Além disso, permite ao usuário que os torrents terminados sejam " -"automaticamente movidos para uma pasta diferente.\n" -"Nota: No momento, arquivos só podem ser movidos dentro da mesma partição." - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Mover Torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "Trocar onde o torrent foi salvo" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Escolha um diretório para mover os arquivos" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Você não pode mover o torrent para uma partição diferente. Por favor " -"verifique suas preferências. Além disso, você não pode mover arquivos " -"torrent para o mesmo diretório no qual ele já está armazenado ou mover " -"arquivos de torrent antes que seus arquivos estejam criados realmente." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Mover os downloads completos para:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "Cancelar" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "OK" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Esse plugin permite aos usuários adicionar web seeds aos seus torrents." - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Adicionar Semente Web" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Adicionar Semente Web" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Limite de download:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Limite de upload:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Torrents ativos:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Slots de Upload:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Máximo de conexões:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Configurações do Agendador" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"A verde estão os limites máximos, a amarelo os mínimos e a vermelho estão " -"parados" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Se o limite está definido para -1, é ilimitado" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Configuração da Interface Web" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Número da Porta" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nova senha" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Nova Senha (confirmação)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Modelo" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Estilo do Botão" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Modelo de cache" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Texto e imagem" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Somente imagem" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Somente texto" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Senha confirmada <> Nova senha\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "traduzir alguma coisa" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Escolha uma url ou um torrent, não ambos." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "sem dados." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "atualização deve ser > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# de Arquivos" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Sobre" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Adicionar torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Aplicar" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Auto atualizar:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Disp" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Configuração" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Informações de saída" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Deletar arquivos recebidos." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Desabilitar" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Recebidos" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Habilitar" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Erro" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "ETA" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Nome de usuário" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Desconectar" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Próximo Anúncio" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Desativado" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Senha inválida, tente novamente" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pausar todos" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Partes" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Descer na fila" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Posição na fila" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Subir na fila" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Re-anunciar" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Atualizar página a cada:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Remover torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Continuar todos" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Definir" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Definir tempo de esgotamento" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Velocidade" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Iníciar" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Enviar" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Lista de torrents" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Tamanho Total" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Rastreador" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Estado do Rastreador" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Enviar torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Enviado" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "segundos" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"A feed será recebida automaticamente, de acordo com o intervalo de " -"atualização." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "As feeds devem ser atualizadas manualmente" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Desativado" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Intervalo de Atualização" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feeds" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tipo" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Fontes de Notícias" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informação" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Padrões" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "De" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Temporada" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episódio" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Através" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Histórico de Restrição" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Não corresponde" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Ano" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Mês" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Dia" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Testar" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Inserir torrent no cimo da fla" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Definir estado como pausado" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Apagar filtro quando correspondido" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Download" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Substituição" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Padrão" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Reescrever Ligação" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"O conteúdo será gravado no diretório padrão do Deluge, ou um prompt " -"aparecera se nenhum estiver definido." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Padrão Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" -"O conteúdo será automaticamente descarregado para o diretório especificado" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Escolha:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Saída" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtros" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Mostrar o ícone do FlexRSS na barra de ferramentas do Deluge." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Mostrar botão na barra de ferramentas." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interface" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"As feeds serão recebidas e processadas nos seus próprios treads. A aplicação " -"não irá bloquear, mas pode não ser fiável." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Threaded (experimental)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Recuperar Feed" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domínio" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Caminho" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Valor" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Configuração" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Gerenciar Plugins de Busca" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nome:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Adicione um novo mecanismo de busca inserindo um nome e uma URL. Para nome, " -"coloque o nome do mecanismo de busca a ser usado. Para URL, coloque o " -"endereço da página de busca. Os parâmetros de busca do usuário irão " -"substituir qualquer ocorrência de ${query} na URL.\n" -"Por exemplo, uma pesquisa no Google seria:\n" -"Nome: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Ajuda" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Buscar anonimamente por torrents" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Expressão de busca" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Selecione um mecanismo" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Gerenciar mecanismos de busca" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Pesquisar " diff --git a/po/ro.po b/po/ro.po deleted file mode 100644 index eae42a038..000000000 --- a/po/ro.po +++ /dev/null @@ -1,2602 +0,0 @@ -# Romanian translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-26 20:56+0000\n" -"Last-Translator: George Dumitrescu \n" -"Language-Team: Romanian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Adaugă torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Adaugă" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Elimină torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Elimină" - -#: glade/delugegtk.glade:56 -#, fuzzy -msgid "Clear Seeding Torrents" -msgstr "Elimină torrent-ele complete" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Șterge" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Pornește sau reia torrent-ul" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Reia" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Întrerupe torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pauză" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Mută torrent-ul în sus" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "În sus" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Mută torrent-ul în jos" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "În jos" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Schimbă setările Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Preferințe" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Module" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Fișier" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Adaugă torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Adaugă _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "Șterge torenții _compleți" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Modifică" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Module" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Afișare" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Bară de unelte" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detalii" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Coloane" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Mărime" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Stare" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Surse Complete" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -#, fuzzy -msgid "Peers" -msgstr "Parteneri" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Viteza Download" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Viteza Upload" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Timp Rămas" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Disponibilitate" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Raţia" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Ajutor" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Doneaza pentru dezvoltarea Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Donați" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "Pagina principală" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "Întrebări frecvente" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "Comunitate" - -#: glade/delugegtk.glade:515 -#, fuzzy -msgid "Help translate this application" -msgstr "Ajutati la traducerea acestei aplicatii" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Traduceti Aceasta Aplicatie" - -#: glade/delugegtk.glade:539 -#, fuzzy -msgid "Runs the first-time configuration wizard" -msgstr "Porneste ajutorul de configurare initiala" - -#: glade/delugegtk.glade:540 -#, fuzzy -msgid "_Run Configuration Wizard" -msgstr "Po_rneste Ajutorul de Configurare" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Descărcate:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Trimise:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Surse Complete:" - -#: glade/delugegtk.glade:845 -#, fuzzy -msgid "Share Ratio:" -msgstr "Raţia" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Viteză" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Parteneri:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Timp Estimat:" - -#: glade/delugegtk.glade:942 -#, fuzzy -msgid "Pieces:" -msgstr "Porţiuni:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Disponibilitate:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistici" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# fișiere:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Mărime Totală:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Stare Tracker:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Următoarea Actualizare:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Nume:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Cale:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Informație torent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detalii" - -#: glade/dgtkpopups.glade:42 -#, fuzzy -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Sunteti sigur ca vreti sa stergeti torentele " -"selectate?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Şterge fişierele descărcate" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Sterge fisierul .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Arată/Ascunde" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Adaugă un Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Înlatură Torrentele Descărcate" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Deschide Fisier" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Selectează tot" - -#: glade/file_tab_menu.glade:48 -#, fuzzy -msgid "Unselect All" -msgstr "Deselectează tot" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Nu downloada" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Inalt" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Cel mai inalt" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge Îmbina Listele de Trackere" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torentul deja exista in Deluge, ati dori sa imbinati listele de trackere?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Setări Deluge" - -#: glade/preferences_dialog.glade:58 -#, fuzzy -msgid "Ask where to save each download" -msgstr "Întreabă unde să salvez fiecare descărcare" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Selectează Un Director" - -#: glade/preferences_dialog.glade:90 -#, fuzzy -msgid "Store all torrent files in:" -msgstr "Salveaza fisierele de tip torrent in:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -#, fuzzy -msgid "Store all downloads in:" -msgstr "Salvează toate descarcările in:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Locaţie Descarcari" - -#: glade/preferences_dialog.glade:173 -#, fuzzy -msgid "Autoload all torrent files in:" -msgstr "Incarca automat toate fisierele de tip torrent din:" - -#: glade/preferences_dialog.glade:205 -#, fuzzy -msgid "Autoload" -msgstr "Autoincarca" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "Numărul de torente activi concomitent. Setaţi -1 pentru nelimitat." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Numărul maxim de torente active concomitent:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Activeaza opţiunea de selectare a fisierelor inainte de incarcare." - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Arată numai dacă torrentul are mai mult de un fişier" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" -"Mareste prioritatea primelor si ultimelor parti ale fisierelor din torent" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Porneşte Torrentele în starea de pauză" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torente" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Alocarea completa aloca dinainte tot spatiul necesar torentului si previne " -"fragmentarea discului." - -#: glade/preferences_dialog.glade:391 -#, fuzzy -msgid "Use Full Allocation" -msgstr "Foloseste Alocarea In Intregime" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Alocarea compacta aloca spatiu dupa cum este necesar" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Foloseste Alocarea Compacta" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Alocare" - -#: glade/preferences_dialog.glade:458 -#, fuzzy -msgid "Downloads" -msgstr "Descărcări" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Atentie - Schimbarea acestor setari va fi aplicata doar dupa ce reporniti " -"Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "De la:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Către:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge va alege sa foloseasca un port diferit de fiecare data." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Porturi aleatorii" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Verifica Portul Activ" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Portul Activ" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Tabela hash distribuita ar putea imbunatati numarul de conexiuni active." - -#: glade/preferences_dialog.glade:703 -#, fuzzy -msgid "Enable Mainline DHT" -msgstr "Activeaza DHT Mainline" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -#, fuzzy -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "Protocolul de alocare a porturilor NAT" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -#, fuzzy -msgid "Peer Exchange" -msgstr "Schimb intre parteneri" - -#: glade/preferences_dialog.glade:799 -#, fuzzy -msgid "Local Peer Discovery" -msgstr "Detecteaza parteneri locali" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Optiuni suplimentare de retea" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "La Primire" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Dezactivat\n" -"Activat\n" -"Fortat" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "La expediere" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Prefera a cripta intregul flux" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Nivel:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Handshake\n" -"Intregul Flux\n" -"Oricare" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Criptare" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Reţea" - -#: glade/preferences_dialog.glade:1025 -#, fuzzy -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Plaseaza torentele la fund cand incepe furnizarea lor" - -#: glade/preferences_dialog.glade:1037 -#, fuzzy -msgid "Queue new torrents above completed ones" -msgstr "Plaseaza torentele noi deasupra celor terminate" - -#: glade/preferences_dialog.glade:1053 -#, fuzzy -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Opreste furnizarea torentelor cand ratia lor ajunge la:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Inlatura automat torentele care ajung la ratia maxima" - -#: glade/preferences_dialog.glade:1105 -#, fuzzy -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Opreste insamintarea torrentului cin cind timpul expira" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Număr de ore" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "Sterge torrentul automat cind saminta ajunge la timpul maxim" - -#: glade/preferences_dialog.glade:1158 -#, fuzzy -msgid "Seeding" -msgstr "Furnizare" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -#, fuzzy -msgid "Seeding" -msgstr "Furnizare" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Numarul maxim de incercari pe secunda. O valoare mare poate duce la cedarea " -"unor rutere ieftine. Setati -1 pentru nelimitat" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Numarul maxim de incercari de conexiune pe secunda:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -#, fuzzy -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Numarul maxim de sloturi de upload pentru toate torentele. Setati -1 pentru " -"nelimitat." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -#, fuzzy -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Viteza maxima de upload pentru toate torentele. Setati -1 pentru nelimitat." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -#, fuzzy -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Viteza maxima de descarcare pentru toate torentele. Setati -1 pentru " -"nelimitat." - -#: glade/preferences_dialog.glade:1317 -#, fuzzy -msgid "Maximum Download Speed (KiB/s):" -msgstr "Viteza maxima de descarcare (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Numarul maxim de conexiuni permis. Setati -1 pentru nelimitat." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -#, fuzzy -msgid "Maximum Connections:" -msgstr "Numarul maxim de conexiuni:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -#, fuzzy -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Viteza maxima de upload (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -#, fuzzy -msgid "Maximum Upload Slots:" -msgstr "Numarul maxim de sloturi de upload:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -#, fuzzy -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Numarul maxim de conexiuni semi-deschise. O valoare mare ar putea sa " -"blocheze unele routere ieftine. Setati -1 pentru nelimitat." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -#, fuzzy -msgid "Maximum Half-Open Connections:" -msgstr "Numarul maxim de conexiuni semi-deschise." - -#: glade/preferences_dialog.glade:1441 -#, fuzzy -msgid "Global Bandwidth Usage" -msgstr "Intrebuintarea globala a largimii de banda" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -#, fuzzy -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Numarul maxim de sloturi de upload per torent. Setati -1 pentru nelimitat." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -#, fuzzy -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Numarul maxim de conexiuni per torent. Setati -1 pentru nelimitat." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Intrebuintarea largimii de banda per torent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Largime de banda" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Afecteaza parteneri uzuali bittorrent" - -#: glade/preferences_dialog.glade:1620 -#, fuzzy -msgid "Peer Proxy" -msgstr "Proxy parteneri" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Nici unul\n" -"Socksv4\n" -"Socksv5\n" -"Socksv6 cu Autentificare\n" -"HTTP\n" -"HTTP cu autentificare" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Parolă" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Nume" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Tip Proxy" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Proxy parteneri" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Proxy Tracker" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Proxy Tracker" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Proxy DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Proxy DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Proxy furnizare Web" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Proxy furnizare Web" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxiuri" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Activează iconiţa din tray" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimizează in tray la închidere" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Porneste in tray" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Tray protejat cu parola" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Parola:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Tray" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Foloseste bara de progres avansata (foloseste ceva mai mult CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Bara de Progres Detaliata" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge va verifica serverele si va va informa daca a fost lansata o noua " -"versiune" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Stati la curent cu noile versiuni" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Update-uri" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Ajutati-ne sa imbunatatim Deluge trimitandu-ne versiunile voastre\n" -"Python si PyGTK, ale sistemului de operare si tipurile procesoarelor.\n" -"Nici un fel de alta informatie nu este trimisa." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Informatii despre sistem" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Altele" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Forteaza verificarea integritatii datelor" - -#: glade/torrent_menu.glade:33 -#, fuzzy -msgid "Re_sume" -msgstr "Continua" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "Intrerupe" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "Ste_rge Torent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "Opţiuni tracker" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "Act_ualizare Tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "Modifica Track_ere" - -#: glade/torrent_menu.glade:138 -#, fuzzy -msgid "_Scrape Tracker" -msgstr "Rade tracker-ul" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "Coada" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Varf" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Sus" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Jos" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Baza" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "Deschide Directorul continator" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "Afiseaza Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "Continua Toate" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "Intrerupe Toate" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Viteza limita descarcare" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Viteza limita upload" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "Ieşire" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Modifica Trackerele" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Modificare Tracker" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge Selectare fisiere" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torentul nu va fi distribuit pe reteaua fara trackere (DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Setarea optiunii privat" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Configurare Lansare Initiala" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Acest program va va ajuta sa setati Deluge dupa preferintele dumneavoastra. " -"Daca nu ati mai folosit Deluge, luati in seama ca cea mai mare parte a " -"functionalitatii si a caracteristicilor Deluge vin sub forma extensiilor " -"care pot fi accesate dand click pe Extensii in meniul Editare." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge are nevoie de o raza de porturi pe care va incerca sa astepte " -"conexiuni noi. Porturile standard pentru bittorrent sunt 6881-6889, totudi, " -"cei mai multi furnizori Internet blocheaza aceste porturi, asadar va " -"recomandam sa alegeti unele noi, intre 49152 si 65535. Alternativ, puteti " -"seta Deluge sa aleaga porturi aleator pentru dumneavoastra." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Foloseste Porturi Aleatoare" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Ati dori ca Deluge sa descarce automat intro locatie aleasa dinainte, sau " -"ati dori sa specificati locatia de fiecare data?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Intreaba unde sa salvez fiecare fisier" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Salveaza toate descarcarile in: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Va rugam sa selectati viteza de upload pentru conexiunea dumneavoastra, " -"aceasta fiind folosita automat pentru a va recomanda setarile de mai jos" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Numarul maxim de torente active:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Viteza d-voastra de upload:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Ajutatine sa imbunatatim Deluge trimitandu-ne versiunile dumneavoastra\n" -"Python si PyGTK, a sistemului de operare si a tipului de procesor.\n" -"Nici un alt fel de informatie nu va fi trimisa." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" -"Copy text \t \n" -"KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Nelimitat" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Activat" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Alta..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Viteza Descarcare (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Viteza Upload (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge este incuiat" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge este protejat prin parola.\n" -"Pentru a afisa fereastra Deluge va rugam sa introduceti parola" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Infinit" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Nescunoscut" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Nume" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Timp estimat" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Disp." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Raţie" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Doriti sa stergeti vechea sursa a torentului?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Intrerupt %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "La coadă %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Exista o versiune noua Deluge. Ati dori sa fiti trimis la site-ul nostru de " -"download?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Conexiuni" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Descărcat" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Incarcare" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Client Bittorrent Deluge" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Alege un director pentru descărcare" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"S-a intamplat o eroare in timp ce se incerca adaugarea torentului. Se poate " -"ca fisierul dumneavoastra .torrent sa fie corupt." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Eroare necunoscuta de torent duplicat." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Nu este destul spaţiu liber pe Hard dic pentru a continua descarcarea" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Spatiu necesar:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Spatiu disponibil:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Adaugă torrent din URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Adaugă URL-ul .torrent-ului de descărcat" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Atenţie - toate fişierele descărcate ale acestui torrent vor fi şterse!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Sunteti sigur ca vreti sa inlaturati toate torentele in furnizare?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "In asteptare" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Verifica" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Conectare" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Descarcare Metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Descarcare" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Terminat" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Alocare" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "octeti necesari" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" -"Nu este destul spaţiu liber pe Hard dic pentru a continua descarcarea" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Anunt trimis" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Anunt OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Alerta" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "cod HTTP" - -#: src/core.py:776 -msgid "times in a row" -msgstr "repetari consecutive" - -#: src/core.py:788 -msgid "Warning" -msgstr "Avertisment" - -#: src/files.py:77 -msgid "Filename" -msgstr "Nume fişier" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioritate" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Prioritatea fisierelor se poate seta doar folosind alocare completa.\n" -"Va rugam sa schimbati optiunea pentru a dezactiva alocarea compacta si apoi\n" -"sa inlaturati si sa adaugati din nou acest torent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Extensie" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Activat" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Alege un fişier .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Fişiere torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Toate fişierele" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Comanda externa" - -#: src/common.py:207 -msgid "not found" -msgstr "nu s-a gasit" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Descarca si importa diverse blocklist-uri de IP.\n" -"\n" -"Actualmente aceasta extensie suporta PeerGuardian (binar si text),\n" -"SafePeer si liste Emule. Fisierele in format PeerGuardian 7zip nu\n" -"sunt suportate. Fisierele pot fi specificate ca URL-uri sau ca locatii\n" -"pe sistemul de fisiere local.\n" -"\n" -"O pagina cu informatii despre site-uri de download de blocklist-uri\n" -"este disponibila la wiki-ul:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Text (Necomprimat)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Lista IP Emule (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Text (comprimat cu Zip)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Nu descarca URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Nu s-a putut deschide fisierul blocklist" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importate" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP-uri" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blocklist" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "inregistrare" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL Blocklist" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "zile" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Incarca si instaleaza blocklist" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importa" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Terminat" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Leader invalid" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Cod magic invalid" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Versiune invalida" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Seteaza ratia dorita pentru un torent" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "Ratie dorita" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Nesetat" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Nesetat" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Ratie dorita" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Aici sunt afisati partenerii asociati cu fiecare torent si IP-ul, tara, " -"clientul, procentul de descarcare si vitezele de descarcare si de upload.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Adresă IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Client" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Procent Descărcare" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -#, fuzzy -msgid "Torrent Creator" -msgstr "Creator Torent" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Acest torent va fi creat dintr-un singur fisier" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Fisier" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Acest torent va fi creat dintr-un director" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Director:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Sursa" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Salveaza fisierul torent ca:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Incarca acest torent in Deluge pentru furnizare" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Adauga torent nou la coada" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Fisier torent" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackere" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Seederi Web" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Comentarii" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Seteaza campul \"privat\"" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Cu cat sunt mai mici partile, cu atat vor fi mai eficiente transferurile, " -"dar fisierul \".torrent\" in sine va fi mai mare" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Marime Parti:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Avansat" - -#: plugins/TorrentCreator/__init__.py:22 -#, fuzzy -msgid "A torrent creator plugin" -msgstr "Extensie de creare torente" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "Torent _Nou" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Torent Nou" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Creaza Torent Nou" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Salveaza fisierele ca..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Trebuie sa selectati o sursa pentru torent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Trebuie sa selectati un fisier unde sa se salveze torentul." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Optiuni de notificare pentru torente" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" -"Activeaza sunete pentru evenimente (necesita pygame, nu este disponibil pe " -"Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Activeaza pictograma clipitoare" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Activeaza notificari popup (necesita python-notify, nu este disponibil pe " -"Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Determina sa clipeasca pictograma cand torentul se dermina de descarcat " -"si/sau afiseaza un notificare popup" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torent terminat" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Extensie de monitorizare a starii retelei\n" -"\n" -"Scris de Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Stare: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Optiuni de monitorizare a evenimentelor" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Activeaza fisiere de monitorizare" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Fisiere monitorizare" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Partener blocat" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blocare completata" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Descarcare block" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Parte terminata" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Stocare mutata" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Avertizare tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Alerta tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Raspuns tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Anunt tracker" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Eroare Fastresume respins" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Eroare ban partener" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Eroare hash esuat" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Eroare fisier" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Cerere invalida" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Mesaje partener" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torent terminat" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Selectati evenimentele de monitorizat" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Adauga un tab cu un monitor al evenimentelor selectate.\n" -"\n" -"Mesajele cu evenimente vin de la alerte libtorrent.\n" -"Daca vreti ca aceste texte sa fie traduse in limba\n" -"dumneavoastra va trebui sa raportati problema la libtorrent,\n" -"nu deluge.\n" -"\n" -"In privinta fisierelor de monitorizare, acestea sunt salvate\n" -"intr-un director din directorul de configurare deluge. Mesajele\n" -"cu evenimente pentru torente specifice sunt salvate in\n" -"fisiere individuale numite la fel ca si fisierul .torrent asociat.\n" -"Mesajele cu evenimente ce nu sunt specifice unui anumit\n" -"torrent sunt salvate in fisierele numite dupa evenimentele\n" -"respective (ex: peer_messages.log).\n" -"Mesajele cu evenimente din fisierele de monitorizare au\n" -"incluse de asemenea un camp cu timpul. Utilizatorului\n" -"ii revine responsabilitatea de a sterge fisierele cand este\n" -"cazul.\n" -"\n" -"Incepand cu v0.2\n" -"Evenimentele sunt despartite pe ecran. In fisiere nu.\n" -"Evenimentele noi sunt afisate deasupra acum.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Monitor Evenimente" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "mesaj eveniment: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Mesaj partener" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "adresa ip: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "client: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "index parte: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "cod stare: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Repetari consecutive: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "index bloc: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "viteza partener: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Selectati limita de viteza per torent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Viteza _Descarcare Torent" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Viteza Upload Torent" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Viteza Upload Torent (KiB/s);" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Viteza Descarcare Torent (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Extensie Grafic de activitate a retelei\n" -"\n" -"Scrisa de Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Grafic" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Progres" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "S-a produs o eroare incercand sa lansam fisierul." - -#: plugins/TorrentFiles/__init__.py:34 -#, fuzzy -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Acest plugin iti arata fisierele dintr-un torrent si iti permite sa setezi " -"prioritati pentru ele si sa alegi ce vrei sa downloadezi.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Fişiere" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Muta torentul" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -#, fuzzy -msgid "Choose a directory to move files to" -msgstr "Alege un director in care sa mutati fisierele" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Muta downloadurile terminate in:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "Acest plugin permite userilor sa adauge seederi web la torrente" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Adauga Seederi Web" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Adauga Seederi Web" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Setări programate" - -#: plugins/Scheduler/plugin.py:179 -#, fuzzy -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Verde reprezinta limita superioara, galben reprezinta limita inferioara si " -"rosu este oprit." - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Dacă limita este setată -1,atunci e nelimitat" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Configureaza WebUi" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Portul" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Parola noua" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Parola noua (Confirma)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Sablon" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Stil buton" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Text si imagine" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Doar imagine" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Doar text" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Parolă Confirmată <> Parolă Nouă\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "tradu ceva" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Alege un URL sau un torrent, nu amandoua" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "fără date." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "Numarul de fisiere" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Despre" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Adauga torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Aplica" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Ava" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Configureaza" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Sterge fisierele descarcate." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Dezactivează" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Descărcat" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Activează" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Eroare" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "ETA" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Conectare" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Deconectare" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Urmatorul Anunt" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Dezactivat" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Parola e gresita, incearca din nou" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Bucati" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Şterge Torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Aplica" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Vitezã" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Start" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Trimite" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Lista torrentelor" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Mărimea totală" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Stare tracker" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Uploadeaza torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Uploadat" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "secunde" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Dezactivat" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feed-uri" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tip" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informaţii" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Modele" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "De la" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Sezon" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episod" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Nu Se Potriveşte" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "An" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Luna" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Zi" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Introduce Torrent La capătul Coyii" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Download" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Inlocuitor" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Model" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -#, fuzzy -msgid "Link Rewriting" -msgstr "Rescrierea linkurilor" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Delunge implicit" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -#, fuzzy -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Continutul va fi downloadat in directorul specificat." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Alege:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -#, fuzzy -msgid "Output" -msgstr "" -"Copy text \t \n" -"Rezultat" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtre" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -#, fuzzy -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Arata o pictograma FlexRSS in toolbar" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -#, fuzzy -msgid "Show button on toolbar." -msgstr "Arata buton in toolbar" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Interfata" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -#, fuzzy -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Feedurile vor fi aduse si parsate in threaduri proprii. Aplicatia nu va fi " -"blocata, dar poate fi nesigura." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domeniu" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Cale" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Valoare" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -#, fuzzy -msgid "Configuration" -msgstr "Configurare" - -#: plugins/Search/searchdlg.glade:7 -#, fuzzy -msgid "Manage Search Plugins" -msgstr "Aranjeaza extensii de cautare" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Nume:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Adauga un nou motor de cautare introducand un Numa si un URL. Pentru Nume, " -"introduceti numele motorului de cautare ce va fi folosit. Pentru URL, " -"introduceti url-ul paginii de cautare. Interogare utilizatorului va inlocui " -"toate campurile $(query} din URL.\n" -"De exemply, o cautare Google ar fi:\n" -"Nume: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Ajutor" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Text cautare" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Alegeti un motor de cautare" - -#: plugins/Search/__init__.py:105 -#, fuzzy -msgid "Manage Engines" -msgstr "Aranjeaza Motoare" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Cauta " diff --git a/po/ru.po b/po/ru.po deleted file mode 100644 index 5b83a3d3d..000000000 --- a/po/ru.po +++ /dev/null @@ -1,2586 +0,0 @@ -# Russian translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-16 10:09+0000\n" -"Last-Translator: Zhomart \n" -"Language-Team: Russian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" -"X-Poedit-Country: RUSSIAN FEDERATION\n" -"X-Poedit-Language: Russian\n" -"X-Poedit-Bookmarks: 175,-1,-1,-1,-1,-1,-1,-1,-1,-1\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Добавить торрент" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Добавить" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Удалить торрент" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Удалить" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Удалить все раздачи" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Очистить" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Запустить или продолжить торрент" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Продолжить" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Приостановить торрент" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Приостановить" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Переместить торрент вверх" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Вверх" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Переместить торрент вниз" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Вниз" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Изменить настройки программы" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Настройки" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Модули" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Файл" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Добавить торрент" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Добавить _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Удалить завершённые" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Правка" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "_Модули" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Торрент" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Вид" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "Панель _инструментов" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Подробности" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Столбцы" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Размер" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Состояние" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Раздающие" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Узлы" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Приём" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Раздача" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Оставшееся время" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Доступность" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Рейтинг" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Справка" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Пожертвовать на развитие Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "По_жертвовать" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Домашняя страница" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Сообщество" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Помочь перевести эту программу" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Перевести это приложение..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Запустить мастер первоначальной настройки" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Запустить мастер настройки" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Принято:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Роздано:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Раздающие:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Рейтинг:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Скорость:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Узлы:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Оставшееся время:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Части:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Доступность:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Статистика" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Файлов:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Общий размер:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Трекер:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Состояние трекера:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Следующий анонс:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Имя:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Путь:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Информация о торренте" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Подробности" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Вы уверены, что хотите удалить выделенные " -"торренты?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Удалить загруженные файлы" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Удалить файл .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Показать/скрыть" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Добавить торрент..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Удалить завершённые" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Открыть файл" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Выделить всё" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Снять выделение" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Не загружать" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Нормальный" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Высокий" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Самый высокий" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Слияние списков трекеров" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Этот торрент-файл уже был добавлен в программу. Хотите обновить списки " -"трекеров?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Параметры программы" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Запрашивать расположение каждый раз" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Выберите папку" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Сохранять все .torrent файлы в:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Сохранять все загрузки в:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Место загрузки" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" -"Автоматически запускать\n" -".torrent-файлы из:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Автозапуск" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "Количество активных торрентов. Установите -1 для неограниченного." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Максимальное количество активных торрентов:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Выбирать файлы перед загрузкой" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Показывать только если торрент имеет более 1 файла" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" -"Повысить приоритет первой\n" -"и последней части файлов торрента" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Запускать торренты приостановленными" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Торренты" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Полное резервирование выделяет столько места, сколько нужно для загрузки " -"торрента и предотвращает фрагментацию данных" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Полное" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" -"Компактное резервирование выделяет место под торрент по необходимости" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Компактное" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Резервирование" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Загрузки" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Замечание: изменения вступят в силу только после перезапуска Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "От:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "До:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge каждый раз будет автоматически выбирать новый порт." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Случайные порты" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Проверить" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Активный порт:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Распределённая хеш-таблица (DHT) может увеличить количество активных " -"соединений." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Использовать DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "Протокол перенаправления портов NAT" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Обмен узлами" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" -"Обнаружение\n" -"локальных узлов" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Дополнительные сетевые настройки" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Входящее:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Отключено\n" -"Включено\n" -"Принудительно" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Исходящее:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" -"Предпочтительно\n" -"шифровать весь поток" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Уровень:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Установка соединения\n" -"Весь поток\n" -"Оба типа" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Шифрование" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Сеть" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Перемещать торренты вниз очереди при начале раздачи" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Добавлять новые торренты над выполненными" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" -"Прекращать раздачу торрентов,\n" -"когда значение рейтинга достигнет:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Автоматически удалять торренты,\n" -"которые достигли максимального рейтинга раздачи" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" -"Прекращать раздачу торрентов,\n" -"когда время раздачи достигнет:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Количество часов" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" -"Автоматически удалять торренты,\n" -"которые достигли максимального времени раздачи" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Раздача" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Раздача" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Максимальное число попыток соединения в секунду. Высокое значение может " -"нарушить работу некоторых дешёвых маршрутизаторов. -1 - без ограничений." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Максимальное число попыток соединения в секунду:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Максимальное число слотов раздачи. Установите -1 для неограниченного." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Максимальная скорость раздачи для всех торрентов. Установите -1 для " -"неограниченной." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Максимальная скорость приёма для всех торрентов. Установите -1 для " -"неограниченной." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Максимальная скорость приёма (КиБ/с):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" -"Максимально допустимое число соединений. Установите -1 для неограниченного." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Максимум соединений:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Максимальная скорость раздачи (КиБ/с):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Максимум слотов для раздачи:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Максимальное количество полуоткрытых соединений. Высокое значение может " -"нарушить работу некоторых дешёвых маршрутизаторов. Установите -1 для " -"неограниченного." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Максимум полуоткрытых соединений:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Общее использование канала" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Максимальное количество слотов для раздачи на торрент. Установите -1 для " -"неограниченного." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Максимальное количество соединений на торрент. Установите -1 для " -"неограниченного." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Использование канала на торрент" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Ограничения" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Затрагивает обычные узлы BitTorrent" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Прокси для узлов" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Порт" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Сервер" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Нет\n" -"Socks v4\n" -"Socks v5\n" -"Socks v5 (Auth)\n" -"HTTP\n" -"HTTP (Auth)" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Пароль" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Имя пользователя" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Тип прокси" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Прокси для узлов" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Прокси для трекера" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Прокси для трекера" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Прокси для DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Прокси для DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Прокси для веб-раздачи" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Прокси для веб-раздачи" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Прокси" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Значок в области уведомлений" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Сворачивать в область уведомлений при закрытии" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Сворачивать в область уведомлений при запуске" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" -"Защитить паролем\n" -"область уведомлений" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Пароль:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Область уведомлений" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Использовать расширенный индикатор процесса\n" -"(использует чуть больше памяти и ЦП)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Подробный индикатор прогресса" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "Deluge будет проверять серверы на наличие новых версий программы" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Уведомлять о выходе новых версий" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Обновления" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Помогите нам в развитии Deluge, отправив нам\n" -"информацию о версии установленных Python и PyGTK,\n" -"операционной системе и типе процессора.\n" -"Будет отправлена только эта и никакая другая информация." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Информация о системе" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Прочее" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Проверить целостность" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "П_родолжить" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "П_ауза" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Удалить торрент" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "Параметры _трекера" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Обновить трекер" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Изменить трекеры" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Проверить состояние" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Очередь" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "В _самый верх" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Вверх" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "В_низ" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "В с_амый низ" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "От_крыть папку торрента" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Показать Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "П_родолжить все" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "При_остановить все" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Ограничение скорости приёма" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "О_граничение скорости раздачи" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "В_ыйти" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Редактор трекеров" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Изменение трекеров" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Выбор файлов" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" -"Торрент не будет распространяться в сети без трекера (т.е. только с DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Установить флаг приватности" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Настройка при первом запуске" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Этот мастер поможет вам настроить Deluge по вашему вкусу. Если вы не знакомы " -"с Deluge, обратите внимание, что основная часть функциональности и " -"возможностей Deluge реализуется с помощью модулей, которые доступны в меню " -"«Правка/Модули»." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge требуется диапазон портов, которые будут использоваться для входящих " -"соединений. По умолчанию порты для bittorrent 6881-6889, но многие " -"провайдеры блокируют эти порты, поэтому вы можете выбрать любые другие между " -"49152 и 65535. Или же вы можете позволить Deluge автоматически выбирать " -"случайные порты." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Использовать _случайные порты" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Хотите, чтобы Deluge автоматически загружал файлы в определённое место, или " -"хотите каждый раз указывать путь для загружаемых файлов?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Спрашивать, куда сохранять каждый файл" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Сохранять всё в: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Выберите исходящую скорость вашего соединения. По ней будут подобраны " -"остальные настройки" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Максимум активных торрентов:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8К\n" -"56К\n" -"64К\n" -"96К\n" -"128К\n" -"192К\n" -"256К\n" -"384К\n" -"512К\n" -"640К\n" -"768К\n" -"1Мбит\n" -"2Мбит\n" -"10Мбит\n" -"20Мбит\n" -"40Мбит\n" -"50Мбит\n" -"100Мбит" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Исходящая скорость вашего канала:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Помогите нам в развитии Deluge, отправив нам\n" -"информацию о версии установленных Python и PyGTK,\n" -"операционной системе и типе процессора.\n" -"Будет отправлена только эта и никакая другая информация." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Не удалось запустить браузер. Убедитесь, что установлен пакет python-gnome2-" -"extras или попробуйте установить переменным окружения LD_LIBRARY_PATH и " -"MOZILLA_FIVE_HOME значение /usr/lib/firefox." - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KиБ/с" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Без ограничения" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Активно" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Другое..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Скорость приёма (КиБ/с)" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Скорость раздачи (КиБ/с):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge заблокирован" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge защищён паролем.\n" -"Чтобы открыть главное окно, введите пароль" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "∞" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Неизвестно" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Название" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Осталось" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Дост." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Рейтинг" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "Выберите папку для переключения торрент источника в" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Удалить старый файл-источник?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Приостановлено %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "В очереди %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "Доступна новая версия Deluge. Хотите перейти на веб-сайт программы?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Соединения" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Приём" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Раздача" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Клиент Bittorrent Deluge" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Укажите директорию для загрузки" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Произошла ошибка во время добавления торрента. Возможно ваш .torrent файл " -"повреждён." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Неизвестная ошибка копирования торрента." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Недостаточно места на диске, чтобы завершить загрузку." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Необходимо на диске:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Доступно на диске:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Добавить торрент из URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Введите URL файла .torrent для загрузки" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Внимание - все загруженные файлы этого торрента будут удалены!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Вы уверены, что хотите удалить все раздаваемые торренты?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "В очереди" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Идёт проверка" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Подключение" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Получение метаданных" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Приём" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Готово" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Резервирование" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "байт необходимо" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Недостаточно свободного места на диске для завершения закачки." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Анонс послан" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Анонс успешно выполнен" - -#: src/core.py:774 -msgid "Alert" -msgstr "Предупреждение" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP код" - -#: src/core.py:776 -msgid "times in a row" -msgstr "попыток подряд" - -#: src/core.py:788 -msgid "Warning" -msgstr "Внимание" - -#: src/files.py:77 -msgid "Filename" -msgstr "Имя файла" - -#: src/files.py:82 -msgid "Priority" -msgstr "Приоритет" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Приоритет файла может быть установлен только при использовании полного " -"резервирования.\n" -"Пожалуйста включите в настройках полное резервирование, затем удалите " -"торрент и добавьте его снова." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Модуль" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Включён" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge — свободное ПО, вы можете распространять и/или\n" -"изменять его на условиях лицензии GNU GPL,\n" -"опубликованной Free Software Foundation, версии 2 или\n" -"любой более поздней версии. Deluge распространяется в\n" -"надежде, что он будет полезен, но БЕЗ ВСЯКИХ ГАРАНТИЙ, даже \n" -"без подразумеваемой гарантии материальной ответственности\n" -"или пригодности для определённых целей. Читайте GNU General\n" -"Public License для уточнения подробностей. Вы должны были\n" -"получить копию GNU General Public License вместе с Deluge.\n" -"Если нет, пишите в Free Software Foundation Inc.,\n" -"51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Выберите файл .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Файлы .torrent" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Все файлы" - -#: src/common.py:88 -msgid "KiB" -msgstr "КиБ" - -#: src/common.py:91 -msgid "MiB" -msgstr "МиБ" - -#: src/common.py:94 -msgid "GiB" -msgstr "ГиБ" - -#: src/common.py:97 -msgid "TiB" -msgstr "ТиБ" - -#: src/common.py:99 -msgid "PiB" -msgstr "ПиБ" - -#: src/common.py:206 -msgid "External command" -msgstr "Внешняя команда" - -#: src/common.py:207 -msgid "not found" -msgstr "не найден" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Загрузить и импортировать списки заблокированных IP.\n" -"\n" -"Сейчас этот модуль умеет обрабатывать списки PeerGuardian\n" -"(двоичный и текстовый), SafePeer и Emule. Файлы PeerGuardian,\n" -"в формате 7zip не поддерживаются. Файлы могут быть указаны\n" -"как URL или как пути в локальной файловой системе.\n" -"\n" -"Страница со ссылками на сайты с блоклистами доступна в вики:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian текст (несжатый)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Список IP Emule (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer текст (zip)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Не удалось загрузить URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Не удалось открыть файл с чёрным списком" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Неверный тип файла или повреждённый файл с чёрным списком" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Импортировано" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Чёрный список" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "записи" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL чёрного списка" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "Загружать новый чёрный список каждые" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "дней" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Чёрный список загружается и устанавливается" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Идёт импорт" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Готово" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Ошибка формата zip-файла:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Ожидался gzip файл, а получен какой-то другой, возможно просто испорченный. " -"Пожалуйста, проверьте настройки блоклистов" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Неверное начало" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Неверный отпечаток" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Неверная версия" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Установить желаемый коэффициент для торрента" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Желаемый рейтинг" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Не установлен" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Не установлен" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Желаемый рейтинг" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Этот модуль показывает всех пиров для каждого торрента, показывает их IP, " -"страну, клиента, процент готовности и скорости загрузки/отдачи.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP-адрес" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Клиент" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Процент завершённости" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Создание торрентов" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Торрент будет сделан из одного файла" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Файл:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Торрент будет создан из директории" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Папка:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Источник" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Сохранить торрент как:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Загрузить торрент в Deluge для раздачи" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Добавить торрент в очередь" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Файл торрента" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Трекеры" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Веб-раздачи" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Комментарии" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Автор" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Установить флаг приватности" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Чем меньше части, тем эффективнее будет обмен ими, но тем больше будет файл " -".torrent" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 КиБ\n" -"64 КиБ\n" -"128 КиБ\n" -"256 КиБ\n" -"512 КиБ\n" -"1024 КиБ\n" -"2048 КиБ\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Размер части:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Дополнительно" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Модуль создания торрентов" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Новый торрент" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Новый торрент" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Создать новый торрент" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Сохранить файл как..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Вы должны выбрать источник для торрента" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Вы должны выбрать файл для сохранения торрента" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Настройки уведомлений торрентов" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Включить звуки событий (требует pygame, недоступно на Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Включить мигающий значок в области уведомлений" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Включить всплывающие подсказки (требует python-notify, недоступно в Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Мигать значком в системном лотке и/или показывать всплывающее уведомление" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Торрент завершён" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Модуль Монитор состояния сети\n" -"\n" -"Автор: Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Состояние: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Настройки журнала событий" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Включить файлы журнала" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Файлы журнала" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Узел заблокирован" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Блок завершён" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Загрузка блока" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Часть завершена" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Хранилище перемещено" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Предупреждение трекера" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Тревога трекера" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Ответ трекера" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Обновление трекера" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Ошибка: быстрое продолжение не удалось" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Ошибка блокирования узла" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Ошибка хеша" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Ошибка файла" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Недопустимый запрос" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Сообщения узлов" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Торрент завершён" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Выберите события для записи в журнал" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Добавляет вкладку с журналом выбранных событий.\n" -"\n" -"Сообщения событий получаются из сигналов libtorrent.\n" -"Если хотите видеть эти сообщения на своём языке,\n" -"сообщите об этом переводчикам libtorrent, а не Deluge.\n" -"\n" -"Файлы журналов будут сохраняться в директорию\n" -"внутри директории с настройками Deluge (скорее всего это ~/.deluge).\n" -"Журналы каждого торрента сохраняются с в отдельных файлах\n" -"с тем же именем, что и у файла .torrent.\n" -"Журналы не относящиеся к торрентам сохраняются в файлы с\n" -"именами по названиям событий (например peer_messages.log).\n" -"Все события в журнале включают время.\n" -"Старые журналы не удаляются.\n" -"\n" -"С версии 0.2\n" -"Длина журнала в окне ограничена. В файлах — нет.\n" -"Новые события теперь показываются сверху.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Журнал событий" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "сообщение: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "торрент: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Сообщение узла" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip-адрес: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "клиент: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "индекс части: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "код статуса: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Повторов: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "индекс блока: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "скорость узла: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Установка ограничения скорости для каждого торрента." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Скорость _приёма торрента" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Скорость _раздачи торрента" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Скорость раздачи (КиБ/с):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Скорость приёма (КиБ/с):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Модуль График сетевой активности\n" -"\n" -"Автор: Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "График" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Выполнено" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Во время запуска файла произошла ошибка." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Этот модуль показывает файлы внутри торрента, позволяет менять их приоритеты " -"и выбирать, какие из них следует загружать.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Файлы" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"Этот модуль позволяет пользователям перемещать торренты в другие папки без " -"необходимости удалять и снова добавлять торрент. Это действие можно " -"выполнить из контекстного меню торрента.\n" -"Кроме того, он позволяет пользователю автоматически перемещать завершённые " -"торренты в другую папку.\n" -"Примечание: Файлы в настоящее время могут быть перемещены только в рамках " -"одного и того же раздела" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "Пере_местить торрент" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Переключить источник торрента" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Выберите директорию для переноса файлов" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Нельзя перенести торрент на другой раздел. Проверьте настройки. Также нельзя " -"перенести файлы торрента в ту же директорию, где они находятся, или " -"перенести файлы торрента до того, как они были созданы." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Переместить завершённые загрузки в:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "Этот модуль позволяет добавлять веб-раздачи к торрентам" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "Добавить _веб-раздачу" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Добавить веб-раздачу" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Лимит приёма:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Лимит раздачи:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Активные торренты:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Слоты для раздачи:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Максимум соединений:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Настройки планировщика" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Зелёный — верхний предел, жёлтый — нижний предел, красный — остановка" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Значение -1 - без ограничений." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Настройка WebUi" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Номер порта" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Новый пароль" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Новый пароль (ещё раз)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Шаблон" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Стиль кнопки" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Кэшировать шаблоны" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Текст и изображения" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Только изображения" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Только текст" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Пароли не совпадают\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "переведите что-нибудь" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Выберите или URL, или торрент, что-то одно." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "нет данных." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "интервал должен быть > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "Количество файлов" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "О программе" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Добавить торрент" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Применить" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Автообновление:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Дост" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Настройка" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Отладка: дамп данных" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Удалить загруженные файлы." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Отключить" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Принято" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Включить" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Ошибка" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Осталось" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Войти" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Выйти" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Следующий анонс" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Выкл" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Неверный пароль, попробуйте ещё раз" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Приостановить все" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Части" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Ниже" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Позиция в очереди" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Выше" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Анонсировать ещё раз" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Обновлять страницу каждые:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Удалить торрент" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Продолжить все" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Установить" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Установить таймаут" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Скорость" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Запустить" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Отправить" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Список торрентов" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Общий размер" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Трекер" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Состояние трекера" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Раздать торрент" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Роздано" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "секунд(ы)" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Лента будет обновляться автоматически, с заданным интервалом." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Лента должна быть обновлена вручную." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Откл." - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Интервал обновления" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Ленты" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Тип" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Лента" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Информация" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Шаблоны" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "От" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Сезон" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Эпизод" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Через" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Ограничение истории" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Не совпадает" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Год" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Месяц" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "День" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Тест" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Вставить торрент в начало очереди." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Приостановить." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Удалить фильтр при совпадении." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Загрузка" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Замена" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Шаблон" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Подмена ссылок" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Содержимое будет загружено в директорию заданную в настройках Deluge по " -"умолчанию, или будет выдан запрос, если она не задана." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "По умолчанию" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Содержимое будет автоматически загружено в указанную директорию." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Выберите:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Вывод" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Фильтры" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Показывать значок FlexRSS в панели инструментов Deluge." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Показать кнопку на панели инструментов." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Интерфейс" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Ленты будут получены и разобраны в отдельных потоках. Приложение не будет " -"блокировано, но может стать нестабильным." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Многопоточность (экспериментально)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Получение лент" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Домен" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Путь" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Значение" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Настройка" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Управление настройками поиска" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Название:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Для добавления нового поисковика задайте для него Имя и URL. Имя — название " -"поисковика, которое будет использоваться. URL — адрес страницы поиска. Поле " -"${query} в заданном URL будет заменено на строку поиска.\n" -"Например поиск в Google будет выглядеть так:\n" -"Имя: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Справка" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Анонимный поиск торрентов" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Строка поиска" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Выберите поисковик" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Управление поисковиками" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Найти " diff --git a/po/si.po b/po/si.po deleted file mode 100644 index ecb22a3ed..000000000 --- a/po/si.po +++ /dev/null @@ -1,2388 +0,0 @@ -# Sinhalese translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2007-10-20 04:07+0000\n" -"Last-Translator: FULL NAME \n" -"Language-Team: Sinhalese \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/sk.po b/po/sk.po deleted file mode 100644 index 645789122..000000000 --- a/po/sk.po +++ /dev/null @@ -1,2589 +0,0 @@ -# Slovak translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# Martin , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-01-20 11:54+0000\n" -"Last-Translator: Martin \n" -"Language-Team: Slovak \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#~ msgid "High download limit:" -#~ msgstr "Rýchly limit sťahovania:" - -#~ msgid "High upload limit:" -#~ msgstr "Rýchly limit odosielania:" - -#~ msgid "Low download limit:" -#~ msgstr "Pomalý limit sťahovania:" - -#~ msgid "Low upload limit:" -#~ msgstr "Pomalý limit odosielania:" - -#~ msgid "Go" -#~ msgstr "Prejsť" - -#~ msgid "Bookmarks" -#~ msgstr "Záložky" - -#~ msgid "Internal Browser" -#~ msgstr "Interný prehliadač" - -#~ msgid "Show the search bar on the toolbar" -#~ msgstr "Zobraziť vyhľadávanie na paneli nástrojov" - -#~ msgid "Browser" -#~ msgstr "Prehliadač" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Pridá torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Pridať" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Odstráni torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Odstrániť" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Vyčistí seedujúce torrenty" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Vyčistiť" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Spustí alebo pokračuje v torrente" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Pokračovať" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pozastaví torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pozastaviť" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Vyššie vo fronte" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Vyššie" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Nižšie vo fronte" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Nižšie" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Zmena nastavení programu Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Nastavenia" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Zásuvné moduly" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Súbor" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Pridať torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Pridať _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Vyčistiť dokončené" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Upraviť" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "_Moduly" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Zobraziť" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Panel nástrojov" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Podrobnosti" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Stĺpce" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Veľkosť" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Stav" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Seederi" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Peeri" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Sťahovanie" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Odosielanie" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Zostávajúci čas" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Dostupnosť" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Pomer zdieľania" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Pomocník" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Stránka" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_Otázky" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Komunita" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Pomôžte s prekladom tejto aplikácie" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Preložiť túto aplikáciu..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Spustí sprievodcu úvodným nastavením" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Spustiť sprievodcu nastavením" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Stiahnuté:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Odoslané:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Seederi:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Pomer zdieľania:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Rýchlosť:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Peeri:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Odhadovaný čas:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Diely:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Dostupnosť:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Štatistika" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Počet súborov:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Celková veľkosť:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Stav trackeru:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Najbližšie oznámenie:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Názov:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Cesta:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Informácie o torrente" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Podrobnosti" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Naozaj chcete odstrániť tieto torrenty z programu " -"Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Zmazať stiahnuté súbory" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Zmazať .torrent súbor" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Zobraziť/Skryť" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Pridať torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Vyčistiť dokončené" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Otvoriť súbor" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Označiť všetky" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Odznačiť všetky" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Nesťahovať" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normálna" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Vysoká" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Najvyššia" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Spojenie zoznamov trackerov v Deluge" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Tento torrent sa už v programe Deluge nachádza, majú sa zlúčiť zoznamy " -"trackerov?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Nastavenia programu Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Vždy sa spýtať, kam ukladať" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Vybrať priečinok" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Uchovávať všetky torrent súbory v:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Vždy ukladať do priečinku:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Miesto kam sťahovať" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Automaticky načítať všetky torrent súbory v:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Autonačítanie" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Počet aktívnych torrentov v programe Deluge. Nastavte -1 pre neobmedzené " -"množstvo." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maximum súčasne aktívnych torrentov:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Pred začatím sťahovania ponúknuť výber súborov na stiahnutie" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Ponúknuť, iba ak má torrent viac než jeden súbor" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Prvý a posledný diel v torrente má prioritu" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Spustiť torrenty pozastavené" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrenty" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Plná alokácia dopredu obsadí potrebné miesto pre torrent, čím sa predchádza " -"fragmentácii disku" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Plná alokácia" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Kompaktná alokácia obsadí iba potrebný diskový priestor" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Kompaktná alokácia" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Alokácia" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Prenosy" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Zmeny v týchto nastaveniach sa prejavia až po reštarte programu " -"Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Od:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Do:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge zakaždým automaticky zvolí iný port." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Náhodný port" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Testovať aktívny port" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktívny port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Distribovaná hašovacia tabuľka môže zlepšiť počet aktívnych spojení." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Povoliť mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT protokol pre mapovanie portov" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Peer Exchange" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Local Peer Discovery" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Rozširujúce sieťové funkcie" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Prichádzajúce:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Vypnuté\n" -"Zapnuté\n" -"Vyžadované" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Odchádzajúce:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Uprednostniť šifrovanie celého toku" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Uroveň:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Začiatok prenosu\n" -"Celý tok\n" -"Všetko" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Šifrovanie" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Sieť" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Zaradiť torrenty na koniec keď začne seedovanie" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Zaradiť nové torrenty nad dokončené" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Prestať seedovať torrent, keď jeho pomer zdieľania dosiahne:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Automaticky vyčistiť torrenty po dosiahnutí pomeru zdieľania" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Seedovanie" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Seedovanie" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Maximálny počet pokusov o spojenie za sekundu. Veľký počet môže zahltiť " -"menej výkonné routery. Nastavte -1 pre neobmedzené." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Maximálny počet pokusov o spojenie za sekundu:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Maximálny počet slotov odosielania všetkých torrentov. Nastavením -1 zrušíte " -"obmedzenie." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maximálna celková rýchlosť odosielania. Nastavením -1 zrušíte obmedzenie." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maximálna celková rýchlosť sťahovania. Nastavením -1 zrušíte obmedzenie." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maximálna rýchlosť sťahovania (KB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" -"Maximálny počet povolených spojení. Nastavením -1 zrušíte obmedzenie." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maximum spojení:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maximálna rýchlosť odosielania (KB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maximálny počet slotov pre odosielanie:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Maximálny počet polootvorených spojení. Vysoký počet môže zahltiť menej " -"výkonné routery. Nastavením -1 zrušíte obmedzenie." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maximálny počet polootvorených spojení:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Celkové využitie prenosového pásma" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Maximálny počet slotov odosielania pre torrent. Nastavením -1 zrušíte " -"obmedzenie." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Maximálny počet spojení na torrent. Nastavte -1 pre neobmedzené." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Využitie prenosového pásma na torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Prenosové pásmo" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Ovplyvňuje bittorrent peerov" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Peer proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Žiadne\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Heslo" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Meno používateľa" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Typ proxy" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Peer Proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Proxy trackera" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Tracker Proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Web seed proxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Web seed proxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxy servery" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Povoliť ikonu v systémovom paneli" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimalizovať do panelu pri zatvorení" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Spustiť na paneli" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Chrániť systémový panel heslom" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Heslo:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Systémový panel" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Používať pokročilý pás priebehu (využíva trochu viac CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Podrobný pás priebehu" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge navštívi naše servery a oznámi vám, či bola vydaná nová verzia" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Upozorňovať na aktualizácie" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Aktualizácie" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Pomôžte nám zlepšiť Deluge tým, že nám zašlete verzie\n" -"Pythonu a PyGTK a typ OS a procesora. Vôbec žiadne\n" -"iné informácie sa neposielajú." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Systémové informácie" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Iné" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Skontrolovať" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "P_okračovať" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Pozastaviť" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Odstrániť torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "Možnosti _trackeru" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Aktualizovať tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Upraviť trackery" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "Opustiť tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Zaradiť do fronty" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Hore" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Vyššie" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Nižšie" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Dolu" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Otvoriť priečinok, ktorý ho obsahuje" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Zobraziť program Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Pokračovať vo všetkých" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Pozastaviť všetko" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Limit rýchlosti _sťahovania" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Limit rýchlosti _odosielania" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Ukončiť" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Upraviť trackery" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Úprava trackerov" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Výber súborov Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrent nebude distribuovaný na sieti bez trackera (DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Nastaviť príznak „privátny“" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Nastavenie po prvom spustení" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Tento sprievodca vám pomôže nastaviť Deluge podľa vašej chuti. Ak ste novým " -"používateľom, všimnite si prosím, že väčšina funkcionality Deluge je " -"dostupná vo forme modulov, ku ktorým sa dostanete po kliknutí na Moduly v " -"ponuke Upraviť alebo na paneli nástrojov." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Program Deluge potrebuje poznať rozsah portov, na ktorých má čakať na " -"prichádzajúce spojenia. Štandardné porty pre bittorrent sú 6881 až 6889, ale " -"väčšina poskytovateľov pripojenia tieto porty blokuje, preto môžete zvoliť " -"iné v rozmedzí od 49152 do 65535. Alebo môžete nechať Deluge automatictky " -"zvoliť náhodné porty." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Použiť _náhodné porty" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Chcete sťahovať zakaždým do tohoto priečinka alebo si želáte pri každom " -"sťahovaní vybrať priečinok pre sťahovanie?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Pýtať sa kam uložiť každý súbor" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Ukladať všetky sťahovania do: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Prosím, zvoľte rýchlosť odosielania vášho pripojenia. Podľa toho sa vyberú " -"odporúčané hodnoty nasledujúcich nastavení" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maximálny počet aktívnych torrentov:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28,8 k\n" -"56 k\n" -"64 k\n" -"96 k\n" -"128 k\n" -"192 k\n" -"256 k\n" -"384 k\n" -"512 k\n" -"640 k\n" -"768 k\n" -"1 Mbit\n" -"2 Mbit\n" -"10 Mbit\n" -"20 Mbit\n" -"40 Mbit\n" -"50 Mbit\n" -"100 Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Rýchlosť odosielania vášho pripojenia:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Pomôžte nám zlepšiť Deluge tým, že nám zašlete verzie\n" -"jazyka Python a PyGTK a druh OS a procesora. Žiadne\n" -"ďalšie informácie sa neposielajú." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Nepodarilo sa spustiť prehliadač. Skontrolujte, či máte nainštalované python-" -"gnome2-extras alebo skúste nastaviť vaše premenné prostredia LD_LIBRARY_PATH " -"a MOZILLA_FIVE_HOME na /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Neobmedzené" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktvované" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Iné..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Rýchlosť sťahovania (KB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Rýchlosť odosielania (KB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Program Deluge je zamknutý" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Program Deluge je chránený heslom.\n" -"Hlavné okno sa zobrazí po zadaní hesla" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Nekonečne" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Neznáme" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Názov" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Zostáva" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Dostup." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Pomer" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Pozastavené %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Vo fronte %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Bola zistená novšia verzia programu Deluge. Chcete ísť na stránku, odkiaľ ju " -"môžete stiahnuť?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Pripojení" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Sťahovanie" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Odosielanie" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge, klient siete Bittorrent" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Vyberte priečinok, kam sťahovať dáta" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Vyskytla sa chyba pri pokuse o pridanie torrentu. Je možné, že váš .torrent " -"súbor je poškodený." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Neznáma duplicitná chyba torrentu." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Na disku nie je dostatok voľného miesta na dokončenie vášho sťahovania.." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Potrebné miesto:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Dostupné miesto:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Pridať torrent z URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Zadajte URL adresu súboru .torrent, ktorý chcete stiahnuť" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Upozornenie - všetky stiahnuté súbory z tohoto torrentu budú odstránené!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Ste si istý, že chcete odstrániť všetky seedujúce torrenty?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Vo fronte" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Kontroluje sa" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Pripája sa" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Sťahujú sa metadáta" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Sťahuje sa" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Dokončené" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Alokuje sa" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "potrebných bajtov" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Na disku nie je dostatok miesta na dokončenie vášho sťahovania." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Ohlásenie poslané" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Ohlásenie OK" - -#: src/core.py:774 -msgid "Alert" -msgstr "Výstraha" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP kód" - -#: src/core.py:776 -msgid "times in a row" -msgstr "krát za sebou" - -#: src/core.py:788 -msgid "Warning" -msgstr "Upozornenie" - -#: src/files.py:77 -msgid "Filename" -msgstr "Názov súboru" - -#: src/files.py:82 -msgid "Priority" -msgstr "Priorita" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Prioritu súboru je možné nastaviť pri použití plnej alokácie.\n" -"Prosím, vypnite v nastaveniach voľbu „kompaktná alokácia“ a potom znovu " -"pridajte tento torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Modul" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Povolený" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Program Deluge je slobodný softvér; môžete ho redistribuovať a/alebo meniť\n" -"za podmienok GNU General Public License (GNU GPL), ktorú publikovala\n" -"Free Software Foundation; buď verzie 2 alebo (podľa vašej voľby)\n" -"ktorejkoľvek novšej verzie.\n" -"\n" -"Deluge je šírený v nádeji, že bude užitočný, avšak BEZ AKEJKOĽVEK\n" -"ZÁRUKY; neposkytujú sa ani implicitné záruky PREDAJNOSTI alebo VHODNOSTI\n" -"NA URČITÝ ÚČEL. Ďalšie podrobnosti hľadajte v GNU General Public License.\n" -"\n" -"S Deluge ste mali dostať kópiu GNU General Public License. Ak nie, píšte na\n" -"Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA " -"02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Vyberte súbor s príponou .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent súbory" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Všetky súbory" - -#: src/common.py:88 -msgid "KiB" -msgstr "KB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PB" - -#: src/common.py:206 -msgid "External command" -msgstr "Externý príkaz" - -#: src/common.py:207 -msgid "not found" -msgstr "nenájdený" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Stiahnutie a import rozličných zoznamov blokovaných IP.\n" -"\n" -"Momentálne tento modul dokáže pracovať so zoznamami\n" -"PeerGuardian (binány a text), SafePeer a Emule. Súbory PeerGuardian\n" -"vo formáte 7zip nie sú podporované. Súbory je možné zadať ako\n" -"URL alebo umiestnenie na lokálnom disku.\n" -"\n" -"Stránka odkazujúca na zoznamy blokovaných IP je dostupná na wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian text (nekomprimovaný)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Zoznam IP Emule (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer text (Zip)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Nepodarilo sa stiahnuť URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Nepodarilo sa otvoriť súbor so zoznamom blokovaní" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Nesprávny typ súboru alebo poškodený súbor zoznamu blokovaných." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importované" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP adresy" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Zoznam blokovaní" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "záznamy" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "URL zoznamu blokovaní" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Načítava a inštaluje sa zoznam blokovaní" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importuje sa" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Dokončené" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Výnimka formátu pre súbor:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Prichádzajúci súbor nie je v požadovanom formáte gzip, alebo je poškodený. " -"Prosím upravte nastavenia vášho zoznamu blokovaných." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Neplatný vodca" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Neplatný magický kód" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Neplatná verzia" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Nastaviť požadovaný pomer pre torrent." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Požadovaný pomer" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Nenastavené" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Nenastavené" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Požadovaný pomer" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Zobrazuje peerov pri každom z torrentov a ich IP adresu, krajinu, klienta, " -"počet stiahnutých percent a rýchlosť sťahovania a odosielania.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP adresa" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klient" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Množstvo dát" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Tvorca torrentu" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Tento torrent sa vytvorí z jediného súboru" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Súbor:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Tento torrent sa vytvorí z adresára" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Adresár:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Zdroj" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Uložiť súbor torrent ako:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Načítať tento torrent do Deluge pre seeding" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Pridať nový torrent do fronty" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent súbor" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackery" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Web seedy" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Komentáre" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Autor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Nastaviť príznak „súkromný“" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Čím menšia veľkosť časti, tým efektívnejšie budú prenosy, ale samotný " -"„.torrent“ súbor bude väčší" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KB\n" -"64 KB\n" -"128 KB\n" -"256 KB\n" -"512 KB\n" -"1024 KB\n" -"2048 KB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Veľkosť časti:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Pokročilé" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Modul Tvorca torrentov" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Nový torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Nový torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Vytvoriť nový torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Uložiť súbor ako..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Musíte vybrať zdroj pre torrent." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Musíte vybrať názov torrent súboru." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Nastavenia upozornenia na torrenty" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" -"Zapnúť zvuky udalostí (vyžaduje pygame, ktorá nie je dostupná na Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Zapnúť blikajúci ikonu v oblasti upozornení" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Zapnúť oznamovanie vyskakovacími oknami (vyžaduje pygame, ktorá nie je " -"dostupná na Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Nech ikona v oblasti upozornení bliká keď sa dokončí sťahovanie torrentu " -"a/alebo príde upozornenie" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent dokončený" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Modul Sledovanie stavu siete\n" -"\n" -"Napísal Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Stav: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Nastavenia záznamu udalostí" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Zapnúť záznam udalostí" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Súbory záznamov" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Peer je zablokovaný" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blokovanie skončilo" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Blokovanie sťahovania" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Časť dokončená" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Úložisko je presunuté" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Upozornenie trackera" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Výstraha trackera" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Odpoveď trackera" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Oznámenie trackera" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Chyba: rýchle obnovenie odmietnuté" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Chyba: blokovaný peerom" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Chybný haš" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Chyba súboru" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Neplatná požiadavka" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Správy peerom" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent je stiahnutý" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Vyberte udalosti, ktoré sa majú zaznamenávať" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Pridá záložku so záznamom zvolených udalostí.\n" -"\n" -"Správy udalostí pochádzajú z výstrah libtorrent.\n" -"Ak chcete, aby tieto správy boli lokalizované do vášho jazyka,\n" -"budete sa o to musieť postarať v projekte libtorrent, nie Deluge.\n" -"\n" -"Čo sa týka súborov záznamov, tie sa ukladajú v adresári\n" -"log v adresári Deluge config. Správy udalostí konkrétnych\n" -"torrentov sa ukladajú do jednotlivých súborov záznamov\n" -"s rovnakýmnázvom ako príslušný .torrent súbor.\n" -"Udalosti správ, ktoré nie sú špecifické pre žiadny torrent\n" -"sa ukladajú do záznamov a sú pomenované podľa udalostí\n" -"(napr. peer_messages.log).\n" -"Správy udalostí v zázname tiež obashujú časovú známku.\n" -"Za čistenie záznamov je zodpovedaný používateľ.\n" -"\n" -"Od verzie 0.2\n" -"Zobrazované udalosti sú odteraz orezané. Súbory záznamov nie.\n" -"Nové udalosti sa zobrazujú navrchu.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Záznam udalostí" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "správa udalosti: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Správa peera" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "IP adresa: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "klient: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "index častí: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "stavový kód: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Časy v poradí: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "index blokov: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "rýchlosť peera: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Zvoľte požadovaný limit rýchlosti na jeden torrent." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Rýchlosť _sťahovania torrentu" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Rýchlosť _odosielania torrentu" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Rýchlosť sťahovania torrentu (KB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Rýchlosť odosielania torrentu (KB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Modul Graf aktivity siete\n" -"\n" -"Napísal Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graf" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Priebeh" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Pri pokuse o spustenie súboru nastala chyba" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Tento zásuvný modul zobrazuje súbory vo vnútri torrentu a umožňuje vám " -"nastaviť pre ne prioritu a vybrať ktoré sa majú stiahnuť a ktoré nie.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Súbory" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Presunúť torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Vyberte adresár, do ktorého sa majú presunúť súbory" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Nemôžete presunúť torrent na iný oddiel. Prosím, skontrolujte svoje " -"nastavenia. Tiež nemôžete presunúť súbory torrentu do adresára, kde sú " -"uložené teraz ani presunúť súbory torrentu predtým, než boli naozaj " -"vytvorené." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Presunúť dokončené sťahovania do:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Tento zásuvný modul umožňuje používateľom pridávať do svojich torrentov web " -"seedy" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Pridať web seed" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Pridať web seed" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Nastavenia plánovača" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Zelené sú rýchle limity, žlté sú pomalé limity a červené je zastavené." - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Limity nastavené na -1 sú neobmedzené." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUi Konfigurácia" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Číslo portu" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nové heslo" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Nové heslo (potvrdiť)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Šablóna" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Štýl tlačidla" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Šablóny cache" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Text a obrázok" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Iba obrázok" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Iba text" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Potvrdené heslo <> nové heslo\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "preložiť niečo" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Vyberte adresu alebo torrent, nie oboje." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "žiadne údaje." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "obnovovanie musí byť > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "Počet súborov" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "O programe" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Pridať torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Použiť" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Automatické obnovovanie:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Dost." - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Nastavenia" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Ladiace dáta" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Odstrániť stiahnuté súbory." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Vypnúť" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Stiahnuté" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Povoliť" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Chyba" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Zostáva" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Prihlásiť sa" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Odhlásiť sa" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Nasledujúce ohlásenie" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Vypnúť" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Heslo je nesprávne, skúste znovu" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pozastaviť všetko" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Časti" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Nižšie vo fronte" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Poradie vo fronte" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Vyššie vo fronte" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Znovuohlásiť" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Obnoviť stránku každých:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Odstrániť torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Pokračovať vo všetkých" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Nastaviť" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Nastaviť interval" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Rýchlosť" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Štart" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Vložiť" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Zoznam torrentov" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Celková veľkosť" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Stav trackeru" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Uploadovať torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Odoslaný" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Adresa" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekúnd" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Kanál bude získavaný pravidelne v stanovenom intervale." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Kanál musí byť obnovený manuálne." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Vypnuté" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Interval obnovovania" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feedy" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Typ" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informácie" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Vzorky" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Od" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Sezóna" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Epizóda" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Cez" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Obmedzenie histórie" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Nezhoduje sa" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Rok" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Mesiac" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Deň" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Vložiť torrent na začiatok fronty." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Zmeniť stav na pozastavený." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Odstrániť filter ak sa zhoduje." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Stiahnuť" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Náhrada" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Vzorka" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Prijímanie odkazov" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Obsah bude uložený do štandardného priečinku Deluge, ak nie je nastavený " -"zobrazí sa výzva." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Predvolené v programe Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Obsah bude automaticky stiahnutý do vybraného adresára." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Vyberte:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Výstup" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtre" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Zobraziť ikonu FlexRSS na paneli programu Deluge." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Zobraziť tlačidlo na paneli." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Rozhranie" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Kanály budú prijímané a spracované vo svojich vláknach. Aplikácia sa " -"nezablokuje, ale môže byť nespoľahlivá." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Vo vláknach (experimentálne)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Preberanie kanálu" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Doména" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Umiestnenie" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Hodnota" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Nastavenia" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Spravovať vyhľadávacie moduly" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Názov:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Pridajte nový vyhľadávač zadaním Názvu a URL. Ako Názov uveďte názov " -"vyhľadávača. Ako URL uveďte URL stránky vyhľadávača. Vyhľadávací reťazec sa " -"vloží na miesto, kde v URL napíšete ${query}.\n" -"Napríklad, vyhľadávanie pomocou Google by bolo:\n" -"Názov: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Pomocník" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Vyhľadávací reťazec" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Zvoľte vyhľadávač" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Spravovať vyhľadávače" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Hľadať " diff --git a/po/sl.po b/po/sl.po deleted file mode 100644 index 087d71c01..000000000 --- a/po/sl.po +++ /dev/null @@ -1,2550 +0,0 @@ -# Slovenian translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-31 14:51+0000\n" -"Last-Translator: Mario Munda \n" -"Language-Team: Slovenian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" -"X-Poedit-Country: SLOVENIA\n" -"X-Poedit-Language: Slovenian\n" -"X-Poedit-SourceCharset: utf-8\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Dodaj torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Dodaj" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Odstrani torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Odstrani" - -#: glade/delugegtk.glade:56 -#, fuzzy -msgid "Clear Seeding Torrents" -msgstr "Počisti sejalne torrente" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Počisti" - -#: glade/delugegtk.glade:79 -#, fuzzy -msgid "Start or Resume Torrent" -msgstr "Začni ali nadaljuj prenos torrenta" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Nadaljuj" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Začasno ustavi torrenta" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Začasno ustavi" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Postavi v vrsti gor" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Gor" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Postavi v vrsti dol" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Dol" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Spremeni nastavitve Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Nastavitve" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Vtičniki" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Datoteka" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Dodaj torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Dodaj _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Počisti končane" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Uredi" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Vt_ičniki" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Pogled" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Orodna vrstica" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Podrobnosti" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "Stolpci" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Velikost" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Stanje" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Sejalci" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Vrstniki" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Hitrost sprejema" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Hitrost nalaganja" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Preostali čas" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Razpoložljivost" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Delilno razmerje" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Pomoč" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Doniraj za razvoj Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Donacije" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Domača stran" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_Pogosto zastavljena vprašanja" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Skupnost" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Pomagaj pri prevodu tega programa" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Prevedi ta program" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Zagon čarovnika konfiguracije" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Zagon čarovnika konfiguracije" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Sprejeto:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Naloženo:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Sejalci:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Delilno razmerje:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Hitrost" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Vrstniki:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "ETA:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Kosi:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Razpoložljivost:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistika" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# datotek:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Skupna velikost:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Sledilnik:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Stanje sledilnika:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Naslednja najava:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Ime:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Pot:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Informacije o torrentu" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Podrobnosti" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Ste prepričani, da želite odstraniti izbrane " -"torrente?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Izbriši prenesene datoteke" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Izbriši .torrent datoteko" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Pokaži/Skrij" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Dodaj Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Odstrani Končane" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Odpri datoteko" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Izberi vse" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Prekliči ves izbor" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Ne prenašaj" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Običajen" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Visoko" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Najvišja" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Združi seznam sledilnikov" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "Torrent v Deluge že obstaja. Želite združiti seznam sledilnikov?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge nastavitve" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Za vsak prenos določi mapo" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Izberi mapo" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Shrani vse torrent datoteke v:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Shrani vse prenose v:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Mesto shranjevanja" - -#: glade/preferences_dialog.glade:173 -#, fuzzy -msgid "Autoload all torrent files in:" -msgstr "Samodejno naloži vse torrent datoteke iz:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Samodejno naloži" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Število aktivnih torrentov, ki jih poganja Deluge. Izberi -1 za neomejeno." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Največ hkrati aktivnih torrentov:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Omogoči izbiranje datotek pred prenosom torrentov" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Pokaži samo, če ima torrent več kot eno datoteko" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Najprej prenesi prve in zadnje koščke torrenta" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Zaženi torrente kot začasno ustavljene" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrenti" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Polna alokacija bo zapolnila celoten prostor, ki ga torrent potrebuje in s " -"tem preprečila razdrobljenost diska." - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Uporabi polno dodelitev" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Kompaktna dodelitev bo dodelila prostor po potrebi" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Uporabi kompaktno dodelitev" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Dodelitev" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Prenosi" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Opomba: Spremembe teh nastavitev bodo uveljavljene ob naslednjem zagonu " -"programa Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Od:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Do:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge bo vsakič samodejno izbral druga vrata." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Naključna vrata" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Preveri vrata" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktivna vrata:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Distribuirana tabela izvlečka lahko izboljša količino aktivnih povezav." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Omogoči DHT sezname" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Univerzalen Vstavi in poženi" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT protokol za mapiranje vrat" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Izmenjava vrstnikov" - -#: glade/preferences_dialog.glade:799 -#, fuzzy -msgid "Local Peer Discovery" -msgstr "Poišči lokalne vrstnike" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Omrežni dodatki" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Vhodno:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Onemogočeno\n" -"Omogočeno\n" -"Vsiljeno" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Izhodno:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Šifriraj celoten pretok" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Stopnja:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Šifriranje" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Omrežje" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Pred začetkom sejanja postavi torrente na dno" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Postavi nove torrente nad končane" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Ustavi sejanje torrentov, ko njihovo delilno razmerje doseže:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Samodejno počisti torrente, ko dosežejo najvišje delilno razmerje" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Ustavi sejanje torrenta, ko čas sejanja doseže:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Ur" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "Avtomatsko odstrani torrente, ki so dosegli maksimalni sejalni čas" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Sejanje" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Sejanje" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Največje število poskusov povezav na sekundo. Visoka vrednost lahko povzroči " -"nestabilno delovanje nekaterih usmerjevalnikov. Postavite -1 za neomejeno." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Največje število poskusov povezav na sekundo:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "Največje število nalaganj za vse torrente. -1 za neomejeno." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "Najvišja hitrost nalaganja vseh torrentov. Izberi -1 za neomejeno." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "Najvišja hitrost prenosa vseh torrentov. Izberi -1 za neomejeno." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Najvišja hitrost prenosa (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Največje število dovoljenih povezav. -1 za neomejeno." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Največje število povezav:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Najvišja hitrost nalaganja (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Največje število nalaganj:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Največ napol odprtih povezav. Visoka vrednost lahko povzroči nestabilno " -"delovanje nekaterih usmerjevalnikov. Postavite -1 za neomejeno." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Največ napol odprtih povezav:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Skupna uporaba pasovne širine" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "Največje število nalagalnih mest na torrent. -1 za neomejeno." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Največ povezav na torrent. -1 za neomejeno." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Uporaba pasovne širine na torrent" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Pasovna širina" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Učinkuje tudi na bittorrent vrstnike" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Proksi vrstnika" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Vrata" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Strežnik" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Brez\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 z avt.\n" -"HTTP\n" -"HTTP z avt." - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Geslo" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Uporabniško Ime" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Vrsta proksija" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Proksi vrstnika" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Proksi sledilnika" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Proksi sledilnika" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Proksi DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Proksi DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Proksi spletnega sejanja" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Proksi spletnega sejanja" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proksiji" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Omogoči ikono v sistemski vrstici" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Pomanjšaj v pladenj ob izhodu" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Zaženi v pladnju" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Zakleni pladenj z geslom" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Geslo" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Sistemska vrstica" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Uporabi napredni indikator poteka (malo večja poraba CPE in pomnilnika)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Napredni indikator napredka" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "Deluge bo preveril, če je na voljo novejša različica" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Obveščanje o novih različicah" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Posodobitve" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Pomagajte nam izboljšati Deluge tako, da nam sporočite različice Python in\n" -" PyGTK, operacijski sistem in vrsto procesorja.\n" -"Nobena druga informacija ne bo poslana." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Sistemske informacije" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Ostali" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Vsili ponovno preverjanje" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "_Nadaljuj" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Začasno ustavi" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "Odst_rani torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Nastavitve sledilnika" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Osveži sledilnik" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "Ur_edi sledilnike" - -#: glade/torrent_menu.glade:138 -#, fuzzy -msgid "_Scrape Tracker" -msgstr "Izmenjaj informacije s sledilnikom" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "Postavi v _vrsto" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Na vrh" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Gor" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Dol" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "Na _dnu" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Odpri mapo" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Pokaži Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Nadaljevanje vseh" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Začasno ustavi vse" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Omejitev hitrosti sprejema" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Omejitev hitrosti nalaganja" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "I_zhod" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Uredi sledilnike" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Urejanje sledilnika" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Izbor datotek" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrent ne bo uvrščen na omrežje brez sledilnikov (DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Označi kot zasebno" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Začetna konfiguracija" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Čarovnik vam bo pomagal nastaviti Deluge po vaši želji. Če ste nov " -"uporabnik, upoštevajte da večji del funkcionalnosti pridobite z vtičniki, do " -"katerih lahko dostopate v meniju pod Uredi in nato Vtičniki oziroma preko " -"orodne vrstice." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge potrebuje območje vrat, preko katerih bo prejemal dohodne povezave. " -"Privzeta vrata so 6881-6889. Lahko se zgodi, da vaš internetni ponudnik " -"blokira ta vrata, zato vam svetujemo, da izberete kakšna druga med 49152 in " -"65535. Lahko pa tudi določite, da Deluge izbere naključna vrata namesto vas." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Uporabi _naključna vrata" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Naj Deluge shrani prenose v določeno mapo ali jo želite vsakič posebej " -"izbrati?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Vprašaj kam shranim vsako datoteko" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Shrani vse prenose v: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Izberi hitrost prenosa povezave, na podlagi katere bomo samodejno " -"prilagodili spodnje nastavitve" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Največ aktivnih torrentov" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Hitrost nalaganja:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Pomagajte nam izboljšati Deluge tako, da nam sporočite\n" -"različice Pythona in PyGTK, operacijski sistem in vrsto procesorja\n" -"Nobeni drugi podatki ne bodo poslani." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"Ne morem uporabiti spletnega brskalnika. Preverite, da imate nameščen paket " -"python-gnome2-extras ali pa določite LD_LIBRARY_PATH in MOZZILA_FIVE_HOME " -"sistemski spremenljivki v /usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Neomejeno" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktivirano" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Drugo..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Hitrost prenosa (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Hitrost nalganja (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge je zaklenjen" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge je zaklenjen z geslom.\n" -"Če želite prikazati Deluge, vpišite geslo." - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Neskončno" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Neznan" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Ime" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Na voljo" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Razmerje" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Začasno ustavljenih %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "V čakalni vrsti %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "Na voljo je nova različica Deluge. Želiš na spletno stran za prenos?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Povezave" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Prejemanje" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Oddajanje" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent Odjemalec" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Izberi mapo za prenos" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Prišlo je do napake pri dodajanju torrenta. Mogoče je datoteka poškodovana." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Neznana napaka podvajanja torrenta" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Na voljo je premalo prostega pomnilnika za dokončanje prenosa." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Potreben prostor:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Razpoložljivi prostor:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Dodaj torrent iz URL naslova" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Vnesite URL naslov .torrent datoteke, ki jo želite prenesti" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Opozorilo - vse prejete datoteke za ta torrent bodo izbrisane!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Ali res želite odstraniti vse sejalne torrente?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "V vrsti" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Preverjam" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Povezujem se" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Prenašam metapodatke" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Prenašanje" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Končano" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Iščem" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "potrebnih bajtov" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Na voljo je premalo prostega pomnilnika za dokončanje prenosa." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Poslana najava" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Najava je v redu" - -#: src/core.py:774 -msgid "Alert" -msgstr "Opozorilo" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP koda" - -#: src/core.py:776 -msgid "times in a row" -msgstr "krat v vrstici" - -#: src/core.py:788 -msgid "Warning" -msgstr "Opozorilo" - -#: src/files.py:77 -msgid "Filename" -msgstr "Ime datoteke" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioriteta" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Prioriteto dtoteke je mogoče določiti samo če uporabljate polno alokacijo.\n" -"Preverite nastavitve in izklopite kompaktno alokacijo, nato odstranite in " -"ponovno dodajte torrent." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Vtičnik" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Omogočeno" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge je brezplačni program. Lahko ga uporabljate\n" -"in spreminjate v skladu s pogoji GNU General Public \n" -"Licence, ki jo določa fundacija Free Software Foundation,\n" -"različica 2 ali katerakoli kasnejša. \n" -"Deluge je narejen v upranju, da bo koristen,\n" -"vendar BREZ KAKRŠNEGAKOLI JAMSTVA.\n" -"Preverite GNU General Public License za podrobnosti.\n" -"Kopija dokumenta GNU General Public License je tudi \n" -"priložena programu Deluge, če ni, to sporočite fundaciji \n" -"Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,\n" -"Boston, MA 02110-1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Izberite .torrent datoteko" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent datoteke" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Vse datoteke" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Zunanji ukaz" - -#: src/common.py:207 -msgid "not found" -msgstr "ne najdem" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Prenos in uvoz različnih seznamov blokiranih IP številk.\n" -"\n" -"Trenutno lahko ta vtičnik upravlja s seznami PeerGuardian (binarni in " -"tekstovni),\n" -"SafePeer in Emules. 7zip datoteke programa PeerGuardian niso podprte.\n" -"Datoteke so lahko posredovane kot URL naslovi ali lokacije lokalnega\n" -"datotečnega sistema.\n" -"\n" -"Prikaz naslovov, ki vsebujejo sezname blokiranih je na voljo na strani:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Text (Nestisnjeno)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP list (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer besedilo (ZIP)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Ne morem prenesti z naslova" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Ne morem odpreti seznama blokiranj" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Napačna vrsta datoteke oziroma napaka v datoteki s črnim seznamom." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Uvoženo" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP številke" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Seznam blokiranj" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "vnosov" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Naslova seznama blokiranj" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dni" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Nalaganje in nameščanje seznama blokiranj" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Uvažam" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Končano" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Izjema v zip datoteki:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Pričakovana je bila gzip datoteka, ki ni ustrezala tej vrsti ali pa je " -"poškodovana. Prosim uredite lastnosti črnega seznama." - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Napaka povzetka" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Napačna magična koda" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Napačna različica" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Določi zaželeno razmerje torrenta." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Zaželeno razmerje" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Ni določeno" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Ni določeno" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Zaželeno razmerje" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Omogoča prikaz vrstnikov, določenih vsakemu torrentu, njihovo IP številko, " -"državo kjer se nahajajo in program, ki ga uporabljajo ter odstotek končanega " -"prenosa in hitrosti prenosov in nalaganj.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP Naslov" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Odjemalec" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Odstotek zaključenosti" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Ustvarjalec torrentov" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Ta torrent bo narejen z vsebino datoteke" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Datoteka:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Ta torrent bo narejen z vsebino mape" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Mapa:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Vir" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Shrani torrent datoteko kot:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Naloži torrent v Deluge za sejanje" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Dodaj nov torrent v vrsto" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent datoteka" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Sledilniki" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Omrežna semena" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Komentarji" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Avtor" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Postavite privatno zastavico" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Manjše kot so velikosti kosov, večji bo učinek prenosa, \".torrent.\" " -"datoteka pa bo večja." - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Velikost kosa:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Napredno" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Vtičnik za ustvarjanje torrentov" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Nov torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Nov torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Ustvari nov torrent" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Shrani datoteko kot ..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Izbrati morate vir torrenta." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Izbrati morate datoteko pod katero se bo shranil torrent." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Lastnosti opomnika torrenta" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Omogoči zvok dogodka (zahteva pygame, ni možno v Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Omogoči utripajočo ikono na pladnju" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Omogoči obvestila v ojavnem oknu (zahteva paket python-notify, ni na voljo " -"na Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Ob končanem prenosu bo ikona v pladnju utripala in/ali prikazala pojavno " -"okno." - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Končan torrent" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Vtičnik prikaza kakovosti omrežne povezave\n" -"\n" -"Napisal Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Povezava: Dobra]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Lastnosti zapisovanja dnevnika" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Omogoči datoteke dnevnika" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Datoteke dnevnika" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Vrstnik je blokiran" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blokiranje končano" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Prenos blokiranj" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Končan kos" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Premik shranjevanja" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Opozorilo sledilnika" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Opozorilo sledilnika" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Odgovor sledilnika" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Najava sledilnika" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Napaka v hitrem nadaljevanju" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Vrstnikova napaka" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Napaka izvlečka" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Napaka v datoteki" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Neveljavna zahteva" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Vrstnikova sporočila" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Končan torrent" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Izbor dogodkov v dnevniku" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Doda zavihek z dnevnikom izbranih dogodkov.\n" -"\n" -"Zapisovanje dogodkov je narejeno s pomočjo knjižnice libtorrent opozoril.\n" -"Če želite prevod besed v vaš jezik, morate to sporočiti,\n" -"upravljalcu knjižnice libtorrent, ne Deluge.\n" -"\n" -"Dnevniki dogodkov so vedno shranjeni v mapo log, ki se \n" -"nahaja v mapi, kjer Deluge shrani konfiguracijske datoteke.\n" -"Sporočila za določene torrente so shranjena v posamezne\n" -"dnevniške datoteke z enakim imenom datoteke, kot jo ima\n" -"izvirna .torrent datoteka.\n" -"Sporočila, ki niso določena za posamezni torrent, so shranjena\n" -"v datoteko z imenom dogodka.\n" -"(na primer peer_messages.log).\n" -"Dogodki v dnevniku so označeni tudi z datumom in uro.\n" -"Uporabnik mora po potrebi sam prazniti dnevniške datoteke.\n" -"\n" -"Od različice v0.2 naprej:\n" -"Prikazi dogodkov so skrajšani. Dnevniške datoteke pa ne.\n" -"Novi dogodki so prikazani na vrhu.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Dnevnik dogodkov" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "sporočilo: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Sporočila vrstnika" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "IP naslov: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "odjemalec: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "indeks kosa: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "koda statusa: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Zapored: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "blokirni seznam: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "hitrost vrstnika: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Nastavi želeno omejitev hitrosti na torrent" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Hitrost _prenosa torrenta" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Hitrost _nalaganja torrenta" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Hitrost nalaganja torrenta (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Hitrost prenosa torrenta (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "Vtičnik grafa mrežne dejavnosti" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graf" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Opravljeno" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Prišlo je od napake med poskusom zagona datoteke." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Ta vtičnik omogoča prikaz datotek znotraj torrenta. Z njim lahko tudi " -"nastavite prioriteto posameznim datotekam ali pa določite katerih ne želite " -"prenesti.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Datoteke" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "Pre_makni torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Izberite mapo v katero želite prestaviti datoteke" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Torrent-a ne morete premakniti na drugo particijo. Prosimo preverite " -"nastavitve. Prav tako ne morete premikati torrent datotek v direktorij v " -"katerem so že, ali preden datoteke sploh obstajajo." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Premakni končane prenose v:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-prekliči" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-v redu" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "Vtičnik omogoči uporabnikom, da torrentom dodajo spletno sejanje" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "Dodaj _Spletno sejanje" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Dodaj omrežno seme" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Omejitev nalaganja:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Aktivni torrenti:" - -#: plugins/Scheduler/plugin.py:116 -#, fuzzy -msgid "Upload Slots:" -msgstr "Reže nalaganja:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Makimalno število povezav:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Nastavitve razporeda" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Zeleno so zgornje meje, rumeno so spodnje meje, rdeča pa pomeni da je " -"ustavljeno" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Če je meja postavljena na -1, to pomeni neskončno." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUi nastavitve" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Številka porta" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Novo geslo" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Novo geslo (potrdi)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Predloga" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Stil gumba" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Predloge predpomnilnika" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Tekst in slika" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Samo slika" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Samo besedilo" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Potrjeno geslo <> Novo geslo\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "prevedite nekaj" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Izberite povezavo ali torrent, ne pa oboje." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "ni podatkov." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "Osveževanje mora biti več kot 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# datotek" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "O programu" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Dodaj torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Uporabi" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Samodejno osveževanje:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Pov" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Nastavi" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Razhroščevanje: odvrži podatke" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Izbriši prenešene podatke" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Onemogoči" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Prenešeno" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Omogoči" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Napaka" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Eta" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Prijava" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Odjava" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Naslednje obvestilo" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Izključeno" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Nepravilno geslo, poskusite znova" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Začasno zaustavi vse" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Kosi" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Premakni po vrsti nazvdol" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Pozicija v vrsti" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Pomakni po vrsti navzgor" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Ponovno oznani" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Osveži stran vsakih:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Odstrani torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Nadaljuj vse prenose" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Nastavi" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Hitrost" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Začni" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Pošlji" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Seznam torrentov" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Celotna velikost" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Sledilnik" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Status sledilnika" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Naloži torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Naloženo" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekund" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Vir se bo, glede na interval posodobitve, povrnil samodejno." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Vsebina se mora sama osvežiti" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Izključeno" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Interval posodobitve" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "URL" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Viri" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tip" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Vir" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Informacije" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Vzorec" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Od" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Sezona" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Epizoda" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -#, fuzzy -msgid "Thru" -msgstr "Do konca" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Omejitve zgodovine" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Ne ustreza" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Leto" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Mesec" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Dan" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Vstavi torrent na vrh vrste" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Nastavi stanje na pavzo." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Izbriši filter ko se ujema" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Prenos" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Zamenjava" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Vzorec" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Prepisovanje povezave" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Vsebina bo shranjena v privzeti direktorij programa Deluge, ali pa se bo " -"pojavil zahtevek po vnosu če ni nastavljen." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Privzeto Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Vsebina bo samodejno shranjena v izbrano mapo." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Izberi:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Izhod" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtri" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Prikaži ikono FlexRSS v orodni vrstici programa Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Prikaži gumb na orodni vrstici" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Vmesnik" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Podatki bodo obdelani v lastni niti. Zaradi tega aplikacija ne bo blokirana, " -"lahko pa da bo nezanesljivo delovala." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Več nitno (eksperimentalno)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Povrnitev vsebine" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domena" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Pot" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Vrednost" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Piškotki" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Konfiguracija" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Uredi iskalnike" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Ime:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Dodaj ime in URL naslov novega iskalnika. Za ime vnesite ime iskalnika. Za " -"URL naslov vnesite naslov iskalne strani. Uporabnikov iskani niz bo zamenjal " -"vse nazive ${query} v URL naslovu.\n" -"Primer za Google iskalnik:\n" -"Ime: Google\n" -"URL naslov: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Pomoč" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Iskani niz" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Izberite iskalnik" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Upravljaj iskalnike" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Najdi " diff --git a/po/sr.po b/po/sr.po deleted file mode 100644 index 0df22de30..000000000 --- a/po/sr.po +++ /dev/null @@ -1,2594 +0,0 @@ -# Serbian translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-01 13:23+0000\n" -"Last-Translator: Vladimir Lazic \n" -"Language-Team: Serbian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Додај торент" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Додај" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Уклони торент" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Уклони" - -#: glade/delugegtk.glade:56 -#, fuzzy -msgid "Clear Seeding Torrents" -msgstr "Очисти сејуће торенте" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Очисти" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Покрени или настави торент" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Настави" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Паузирај торент" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Паузирај" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Промовиши торент у реду чекања" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Горе:" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Деградирај торент у реду чекања" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Доле" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Измени Deluge подешавања" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Подешавања" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Додаци" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Датотека" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "Дод_ај торент" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Додај _УРЛ" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Очисти завршене" - -#: glade/delugegtk.glade:249 -#, fuzzy -msgid "_Edit" -msgstr "Ур_еђивање" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Дод_аци" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Торент" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Преглед" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "Палета _алата" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Детаљи" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Колоне" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Величина" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Статус" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Сејачи:" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -#, fuzzy -msgid "Peers" -msgstr "Садрузи" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Брзина преузимања" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Брзина слања" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Преостало време" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Доступност" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Однос дељења" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "П_омоћ" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Веб страница" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Заједница" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Помозите у преводу ове апликације" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Преведи ову апликацију..." - -#: glade/delugegtk.glade:539 -#, fuzzy -msgid "Runs the first-time configuration wizard" -msgstr "Покреће чаробњака првог покретања" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "Пок_рени чаробњака за подешавања" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Преузето:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Послато:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Сејачи:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Однос дељења:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Брзина:" - -#: glade/delugegtk.glade:904 -#, fuzzy -msgid "Peers:" -msgstr "Садрузи:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Процењено време:" - -#: glade/delugegtk.glade:942 -#, fuzzy -msgid "Pieces:" -msgstr "Делова:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Доступност:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Статистика" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "# датотека:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Укупна величина:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Пратилац:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Стање пратиоца:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Следећа објава:" - -#: glade/delugegtk.glade:1211 -#, fuzzy -msgid "Name:" -msgstr "Назив:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Путања:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Подаци о торенту" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Детаљи" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Да ли сте сигурни да желите уклонити изабране " -"торенте из Deluge-а?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Обриши преузете датотеке" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Обриши .торент датотеку" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Прикажи/сакриј" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Додај торент..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Очисти завршене" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Отвори датотеку" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Одабери све" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Поништи сав избор" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Не преузимај" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -#, fuzzy -msgid "Normal" -msgstr "Нормалан" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -#, fuzzy -msgid "High" -msgstr "Висок" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -#, fuzzy -msgid "Highest" -msgstr "Највиши" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge спајање листи пратилаца" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Торент је већ детектован у Deluge-у, да ли желите да спојите листе пратилаца?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge подешавања" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Питај где сачувати за свако преузимање" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Изаберите фасциклу" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Савучај све торент датотеке у:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Складишти сва преузимања у:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Место преузимања" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Аутоматски учитај све торент датотеке из:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Аутоматско учитавање" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Број активних торента које ће Deluge покренути. Вредност -1 значи " -"неограничено." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Највећи број истовремено активних торента:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Омогући избор датотека за торент пре учитавања" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Покажи само ако торент има више од 1 датотеке" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Стави приоритет на прве и задње делове датотека у торенту" - -#: glade/preferences_dialog.glade:335 -#, fuzzy -msgid "Start torrents in paused state" -msgstr "Покрени торенте у паузираном стању" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Торенти" - -#: glade/preferences_dialog.glade:390 -#, fuzzy -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Пуна алокација унапред одваја простор који је потребан за торент и спречава " -"фрагментацију диска" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Користи пуну алокацију" - -#: glade/preferences_dialog.glade:413 -#, fuzzy -msgid "Compact allocation only allocates space as needed" -msgstr "Компактна алокација одваја простор само када је потребан" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Користи компактну алокацију" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Алокација" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Преузимања" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Молимо обратите пажњу - промене ових подешавања ће бити примењене након " -"поновног покретања Deluge-а." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Од:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "За:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge ће аутоматски ваки пут изабрати различит прикључак." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Насумични портови" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Провери активан порт" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Активан порт:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Расподељена хеш таблица може побољшати број активних конекција." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Омогући главнотоковски DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -#, fuzzy -msgid "Universal Plug and Play" -msgstr "Универзални плаг енд плеј" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "НАТ протокол за мапирање портова" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "НАТ-ПМП" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Размена садруга" - -#: glade/preferences_dialog.glade:799 -#, fuzzy -msgid "Local Peer Discovery" -msgstr "Локално проналажење садруга" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Мрежни додаци" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Долазни:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Искључено\n" -"Укључено\n" -"Обавезно" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Одлазни:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Пожељно шифровање целог тока" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Ниво:" - -#: glade/preferences_dialog.glade:931 -#, fuzzy -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Руковање\n" -"Пун ток\n" -"Оба" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Шифровање" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Мрежа" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Шаљи торенте на крај реда чекања кад почну сејање" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Шаљи нове торенте изнад завршених у реду чекања" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Прекини сејање након што однос дељења достигне:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Аутоматски чисти торенте који досегну максимални однос дељења" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Сејање" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Сејање" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Највећи број покушаја повезивања у секунди. Висока вредност би могла да " -"обори неке јефтине рутере. За неограничено поставите на -1." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Највећи број покушаја повезивања у секунди:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Максималан број слотова за слање за све торенте. Ставите -1 за неограничено." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Максимална брзина слања за све торенте. Вредност -1 значи неограничено." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Максимална брзина преузимања за све торенте. Вредност -1 значи неограничено." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Максимална брзина преузимања (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Максимални дозвољени број веза. Вредност -1 значи неограничено." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Максимални број веза:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Максимална брзина слања (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Највише слотова за слање:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Највећи број полуотворених веза. Висока вредност може да обори неке јефтине " -"рутере. За неограничено поставите на -1." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Највише полуотворених веза:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Глобално заузеће протока" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Највећи број слотова за слање по торенту. За неограничено поставите на -1." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "Највећи број веза по торенту. За неограничено поставите на -1." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Заузеће протока по торенту" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Пропусни опсег" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Утиче на регуларне биторент садруге" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Прокси садруга" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Порт" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Сервер" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Ниједно\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 са ауторизацијом\n" -"HTTP\n" -"HTTP са ауторизацијом" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Лозинка" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Корисничко име" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Врста проксија" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Прокси садруга" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Прокси пратилаца" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Прокси пратилаца" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "Прокси за DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "Прокси за DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Прокси за мрежно сејање" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Прокси за мрежно сејање" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Проксији" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Омогући икону у обавештајној зони" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Смањуј у обавештајну зону панела при затварању" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Покрени у обавештајној зони" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Заштити лозинком обавештајну зону" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Лозинка:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Обавештајна зона" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Користи унапређену траку напретка (троши мало више системских ресураса)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Детаљна трака напретка" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge ће проверити наше сервере и јавити Вам ако је објављена нова верзија" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Будите обавештени о новим верзијама" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Освежења" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Помозите нам да унапредимо Deluge тако што ћете\n" -"нам послати вашу верзију Python-а и PyGTK-а,\n" -"оперативни систем и тип процесора. Апсолутно\n" -"ниједан други податак се не шаље." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Системске информације" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Остало" - -#: glade/torrent_menu.glade:11 -#, fuzzy -msgid "_Force Recheck" -msgstr "_Форсирај проверу" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "На_стави" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Паузирај" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "Уклони то_рент" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "Опције пра_тиоца" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Освежи пратиоца" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "Ур_еди пратиоце" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Одбаци пратиоца" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Ред чекања" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Врх" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Горе" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Доле" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Дно" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Отвори садржавајућу фасциклу" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Прикажи Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Настави све" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Паузирај све" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Ограничење брзине п_реузимања" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Ограничење брзине _слања" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Изађи" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Уреди пратиоце" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Уређивање пратиоца" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Избор датотека за Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Торент неће бити дистрибуиран на мрежи без пратиоца (DHT)" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Постави ознаку за приватно" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Подешавање првог покретања" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Овај чаробњак ће вам помоћи да подесите Deluge по својој вољи. Ако сте нови " -"у Deluge-у, имајте у виду да већина функционалности и могућности истог " -"долази у облику додатака, којима се може приступити кликом на Додаци у " -"менију Уреди или на палети с алаткама." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge-у треба опсег портова на којима ће ослушкивати долазеће везе. " -"Подразумевани портови за биторент су 6881-6889, међутим, многи добављачи " -"интернет услуга (ISP) блокирају те портове, па је препоручљиво да изаберете " -"неке друге између 49152 и 65336. Алтернатива је да подесите да Deluge " -"аутоматски изабира насумичан порт за вас." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Ко_ристи насумичне портове" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Да ли желите да Deluge аутоматски преузима податке на унапред дефинисану " -"локацију или бисте желели да сваки пут сами бирате локацију?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Питај где сачувати сваку датотеку" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Смештај сва преузимања у: " - -#: glade/wizard.glade:215 -#, fuzzy -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Молим одаберите брзину слања за вашу везу, која ће потом бити искоришћена да " -"се аутоматски предложе доња подешавања" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Највише активних торената:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Брзина слања Ваше везе:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Помозите нам да унапредимо Deluge тако што ћете\n" -"нам послати вашу верзију Python-а и PyGTK-а,\n" -"оперативни систем и тип процесора. Апсолутно\n" -"ниједан други податак се не шаље." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Неограничено" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Активирано" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Остало..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Брзина преузимања (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Брзина слања (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge је закључан" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge је заштићен лозинком.\n" -"Да бисте приказали прозорче Deluge-а, молимо вас укуцајте вашу лозинку" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Бесконачност" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Непознато" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Назив" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Процењено време" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Дост." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Однос" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Паузиран %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "На чекању %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Појавила се нова верзија Deluge-а. Да ли желите да одете на сајт за " -"преузимање?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Везе" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Preuzmi" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Слања" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge биторент клијент" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Одабери директоријум за преузимање" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Дошло је до грешке при покушају додавања торента. Могуће је да је ваша " -".torrent датотека неисправна." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Грешка непознатог дуплираног торента." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Нема довољно простора на диску да би се довршило преузимање." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Потребан простор:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Доспутан простор:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Додај торент из УРЛа" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Унеси УРЛ .torrent датотеке за скидање" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Упозорење - све скинуте датотеке за овај торент ће бити обрисане!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Јесте ли сигурни да желите да уклоните све сејуће торенте?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "У ред чекања" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Проверавам" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Повезивање" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Преузимање метаподатака" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Преузимам" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Завршено" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Одвајам" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "је број потребних бајтова" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Нема довољно слободног простора на диску за завршетак преузимања." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Објава послата" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Објава ОК" - -#: src/core.py:774 -msgid "Alert" -msgstr "Упозорење" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP код" - -#: src/core.py:776 -msgid "times in a row" -msgstr "покушаја заредом" - -#: src/core.py:788 -msgid "Warning" -msgstr "Упозорeњe" - -#: src/files.py:77 -msgid "Filename" -msgstr "Име датотеке" - -#: src/files.py:82 -msgid "Priority" -msgstr "Приоритет" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Приоритет датотека је могуће поставити само при пуној алокацији.\n" -"Молимо промените ваша подешавања и онемогућите компактну алокацију, а потом " -"уклоните и поново додајте овај торент." - -#: src/dialogs.py:66 -#, fuzzy -msgid "Plugin" -msgstr "Додаци" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Омогућено" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge је слободан софтвер, можете га даље дистрибуирати и/или\n" -"мењати под условима Опште јавне лиценце ГНУ-а, коју је објавила\n" -"Задужбина за слободни софтвер, било верзије 2 Лиценце,\n" -"или (по вашем избору) било које касније верзије.\n" -"Deluge је дистрибуиран у нади да ће бити користан,\n" -"али без ИКАКВЕ ГАРАНЦИЈЕ, без чак и \n" -"имплицитне гаранције о ТРЖИШНОЈ ВРЕДНОСТИ ИЛИ ПОДЕСНОСТИ\n" -"ЗА ОДРЕЂЕНУ СВРХУ. За више детаља погледајте Општу\n" -"јавну лиценцу ГНУ-а. Требало би да сте добили\n" -"примерак Опште јавне лиценце ГНУ-а уз \n" -"Deluge, у случају да нисте, пишите на Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Изабери .torrent датотеку" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Торент датотеке" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Све датотеке" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "Спољашња команда" - -#: src/common.py:207 -msgid "not found" -msgstr "није нађено" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Скини и увези различите листе блокираних IP адреса.\n" -"\n" -"Овај додатак тренутно може да користи PeerGuardian (бинарне и текстуалне),\n" -"SafePeer и Emule листе. PeerGuardian 7zip датотеке нису подржане.\n" -"Датотеке могу бити одређене преко УРЛ адресе или адресе у локалном\n" -"систему датотека.\n" -"\n" -"Страница са везама ка сајтовима за скидање листа блокирања је доступан\n" -"на викију:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian текст (некомпресован)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP листа (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "„SafePeer“ Текст (компресован)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Није могуће преузети УРЛ" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Не могу да отворим листу блокирања" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Погрешан тип датотеке или неисправна датотека листе блокирања." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Увезено" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "ИП адресе" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Листа блокирања" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "уноси" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "УРЛ листе блокирања" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Учитавам и инсталирам листу блокирања" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Увозим" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Завршено" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Добили смо изузетак за зип датотеку:" - -#: plugins/BlocklistImport/peerguardian.py:24 -#, fuzzy -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Очекивали смо gzip датотеку, али нисмо то добили, а могуће је и да је " -"датотека покварена. Молимо уредите своја подешавања списка блокирања" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Неисправан вођа" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Неисправан магични код" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Неисправна верзија" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Поставите жељену размеру за торент." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "Жељена _размера" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Није постављено" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Није постављено" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Жељена размера" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Ово вам показује садруге повезане са сваким торенто и показује вам њихову IP " -"адресу, земљу, клијента, проценат завршености као и брзине слања и скидања.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP адреса" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Клијент" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Процената завршено" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Креатор торента" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Овај торент ће бити креиран од датотеке" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Датотека:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Овај торент ће бити креиран од директоријума" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Директоријум:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Извор" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Сачувај торент као:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Учитај овај торент у Deluge за сејање" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Додај нови торент у ред за чекање" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Торент датотека" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Пратиоци" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Коментари" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Аутор" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -#, fuzzy -msgid "Set Private Flag" -msgstr "Постави приватну ознаку" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -#, fuzzy -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Пренос је ефикаснији што су делови мањи, али је зато стварна величина " -"\".torrent\" датотеке већа" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Величина дела:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Напредно" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Додатак за креирање торента" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Нови торент" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Нови торент" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Направи нови торент" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Сачувај датотеку као..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Морате изабрати извор за торент." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Морате изабрати датотеку у којој ће бити сачуван торент." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Подешавања обавештења торента" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Омогући звуке за догађаје (захтева pygame, није доступно под Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Омогући трепћућу икону у панелу" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Омогући искачућа обавештења (захтева python-notify, није доступно под Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -#, fuzzy -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Нека икона у панелу трепће када се заврши скидање торента и/или нека искочи " -"обавештење" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Завршен торент" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Додатак Монитор стања мреже\n" -"\n" -"Написао „Kripkenstein“" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Здравље: У реду]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -#, fuzzy -msgid "Event Logging Preferences" -msgstr "Подешавања бележења догађаја" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -#, fuzzy -msgid "Enable log files" -msgstr "Омогући датотеке за бележење" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Датотеке дневника" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Садруг блокиран" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Завршен блок" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Блокирај преузимање" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Део завршен" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Складиште премештено" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Упозоравање пратиоца" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Узбуна пратиоца" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Одговор пратиоца" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Објављивање пратиоцу" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "Грешка у одбијању брзог настављања" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Грешка - забрана садруга" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Грешка - хеш неисправан" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Грешка датотеке" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Погрешан захтев" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Поруке садруга" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Торент завршен" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Одаберите догађаје који ће се записивати" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Додаје картицу са дневником одабраних догађаја.\n" -"\n" -"Свака порука долази од упозорења libtorrent-а.\n" -"Ако желите да преведете ове ниске у свој локал,\n" -"проблем морате да пријавите libtorrent-у, не deluge-у.\n" -"\n" -"Што се датотека дневника тиче, дневници се снимају у\n" -"директоријум дневника у deluge-овом директоријуму за подешавања.\n" -"Поруке о догађајима за одређени торент се чувају у посебним\n" -"датотекама дневника које имају исти назив као и повезана .torrent\n" -"датотека. Поруке о догађајима који нису везани за неки одређени торент\n" -"се чувају у дневницима именованим по догађајима\n" -"(на пример, peer_messages.log).\n" -"Поруке о догађајима у датотекама дневника такође садрже и временску ознаку.\n" -"Корисник је одговоран за чишћење дневника.\n" -"\n" -"Почев од верзије 0.2\n" -"Догађаји се скраћују при приказивању. Поруке у датотека дневника не.\n" -"Нови догађаји су сада приказани на врху.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Дневник догађаја" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "порука догађаја: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "торент: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Порука садруга" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ИП адреса: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "клијент: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "индекс дела: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "код стања: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Пута заредом:: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "Индекс блокова: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "Брзина садруга: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Постављање жељеног ограничење брзине по торенту." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Брзина преу_зимања за торент" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Брзина _слања за торент" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Брзина слања за торент (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Брзина преузимања за торент (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Додатак за графикон мрежне активности\n" -"\n" -"Написао „Kripkenstein“" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Графикон" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Напредак" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Десила се грешка при покушају покретања датотеке." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Овај додатак показује датотеке у торенту и дозвољава постављање приоритета " -"за њих и избор оних које желите или не желите да преузимате.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Датотеке" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "По_мери торент" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Изаберите директоријум у који ће датотеке бити померене" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Не можете да померите торент на другу партицију. Молимо проверите своје " -"поставке. Такође, не можете да померите датотеке торента у исти директоријум " -"у којем се већ налазе нити да померите датотеке торента пре него што су " -"уопште и направљене." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Премести завршена преузимања у:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ок" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "Дод_ај мрежно сејање" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Додај мрежно сејање" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "УРЛ:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Подешавања планера" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Зелено је горње ограничење, жудо је доње ограничење а црвено је заустављено" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Ако је ограничење постављено на -1, то је неограничено." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Подешавање web интерфејса" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Број порта" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Нова лозинка" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Нова лозинка (потврда)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Шаблон" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Стил дугмади" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "Шаблони кеша" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Текст и слика" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Само слика" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Само текст" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "ПОтврђена лозинка <> Нова лозинка\n" - -#: plugins/WebUi/webserver_common.py:62 -#, fuzzy -msgid "translate something" -msgstr "преведите нешто" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Одаберите УРЛ или торент, али не оба" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "нема података." - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "освежавање мора бити > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# датотека" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "О програму" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Додај торент" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Примени" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Аутоматско освежавање" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "Дост" - -#: plugins/WebUi/scripts/template_strings.py:10 -#, fuzzy -msgid "Config" -msgstr "Подешавање" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "Debug:Data Dump" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Обриши преузете датотеке." - -#: plugins/WebUi/scripts/template_strings.py:16 -#, fuzzy -msgid "Disable" -msgstr "Онемогући" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Преузето" - -#: plugins/WebUi/scripts/template_strings.py:22 -#, fuzzy -msgid "Enable" -msgstr "Омогући" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Грешка" - -#: plugins/WebUi/scripts/template_strings.py:24 -#, fuzzy -msgid "Eta" -msgstr "Процена" - -#: plugins/WebUi/scripts/template_strings.py:25 -#, fuzzy -msgid "Login" -msgstr "Пријава" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Одјава" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Следећа објава" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Искључено" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Погрешна лозинка, покушајте поново" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Паузирај све" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Парчићи" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Помери доле" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Помери горе" - -#: plugins/WebUi/scripts/template_strings.py:41 -#, fuzzy -msgid "Reannounce" -msgstr "Поново објави" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Освежи страну сваких:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Уклони торент" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Настави све" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Постави" - -#: plugins/WebUi/scripts/template_strings.py:49 -#, fuzzy -msgid "Set Timeout" -msgstr "Постави истек" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Брзина" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Покрет" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Пошаљи" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Списак торената" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Укупна величина" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Пратилац" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Статус пратиоца" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Пошаљи торент" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Послато" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Урл" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "секунди" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"Довод ће бити аутоматски добављан, у зависности од интервала ажурирања." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Довод мора бити освежен ручно." - -#: plugins/FlexRSS/FlexRSS.glade:116 -#, fuzzy -msgid "Disabled" -msgstr "Онемогућено" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Интервал ажурирања" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "УРЛ" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Доводи" - -#: plugins/FlexRSS/FlexRSS.glade:384 -#, fuzzy -msgid "Type" -msgstr "Тип" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Довод" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Подаци" - -#: plugins/FlexRSS/FlexRSS.glade:511 -#, fuzzy -msgid "Patterns" -msgstr "Обрасци" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Од" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -#, fuzzy -msgid "Season" -msgstr "Сезона" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -#, fuzzy -msgid "Episode" -msgstr "Епизода" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -#, fuzzy -msgid "Thru" -msgstr "Кроз" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Ограничење историје" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Не поклапа се" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Година" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Месец" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Дан" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Тест" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Убаци торент на врх реда." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Постави стање на паузирано." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "Након поклапања обриши филтере." - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Преузимање" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Замена" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Образац" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "Преписивање веза" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" -"Садржај ће бити сачуван у подразумевани директоријум Deluge-а, а ако исти " -"није подешен, биће постављено питање." - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Подразумевано за Deluge" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "Садржај ће бити аутоматски сачуван у одређеном директоријуму." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Одаберите:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Излаз" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Филтери" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Прикажи FlexRSS икону у Deluge-овој траци с алатима." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Прикажи дугме на траци с алатима." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Изглед" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Довод ће бити добављен и обрађен у сопственој нити. Апликација неће бити " -"блокирана, али то може бити непоуздано." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Добављање довода" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Домен" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Путања" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Вредност" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Колачићи" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Подешавање" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Управљање додацима за претрагу" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Име:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Додајте нову машину за претраживање тако што ћете укуцати назив и адресу. За " -"назив, унесите име машине за претраживање које желите. За адресу, унесите " -"тачну адресу машине за претраживање. Корисников упит за претрагу ће заменити " -"било који унос за ${query} у адреси.\n" -"Нпр. Гугл претраживање би било:\n" -"Назив:Гугл\n" -"Адреса:http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Помоћ" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Пронађи низ знакова" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Изабери машину" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Управљање машинама" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Претражи " diff --git a/po/sv.po b/po/sv.po deleted file mode 100644 index 277c5f4a1..000000000 --- a/po/sv.po +++ /dev/null @@ -1,2570 +0,0 @@ -# translation of deluge.po to Swedish -# translation of PACKAGE. -# Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# <>, 2006. -# Daniel Nylander , 2007. -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-30 12:20+0000\n" -"Last-Translator: Ojan \n" -"Language-Team: Swedish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Lägg till torrent-fil" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Lägg till" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Ta bort torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Ta bort" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Töm distribuerade torrent-filer" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Töm" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Starta eller återuppta torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Återuppta" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Pausa torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Pausa" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Flytta torrent-fil uppåt i kön" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Uppåt" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Flytta torrent-fil nedåt i kön" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Nedåt" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Ändra Deluge-inställningar" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Inställningar" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Insticksmoduler" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Arkiv" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Lägg till torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Lägg till _url" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Töm färdiga" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Redigera" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Insticks_moduler" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Visa" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Verktygsrad" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Detaljer" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Kolumner" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Storlek" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Status" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Distributörer" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Klienter" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Hämtningshastighet" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Sändningshastighet" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Återstående tid" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Tillgänglighet" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Utdelningsförhållande" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Hjälp" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Donera till Deluge Development" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Donera" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Hemsida" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_Frågor och svar" - -#: glade/delugegtk.glade:492 -#, fuzzy -msgid "_Community" -msgstr "Mötesplats" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Hjälp till att översätta programmet" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Översätt det här programmet..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Kör konfigureringsguiden" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Kör konfigureringsguide" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Hämtat:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Skickat:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Distributörer:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Utdelningsförhållande:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Hastighet:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Klienter:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Färdig om:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Delar:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Tillgänglighet" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Statistik" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Antal filer:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Total storlek:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Bevakare:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Bevakarstatus:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Nästa annonsering:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Namn:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Sökväg:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrent-info" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detaljer" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Är du säker att du vill ta bort valda torrent-" -"fil(er) från Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Ta bort hämtade filer" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Ta bort torrent-fil" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Visa/dölj" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Lägg till en torrent-fil..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Töm färdiga" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Öppna fil" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Markera alla" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Avmarkera alla" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Hämta inte" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Hög" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Högsta" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge sammanfoga bevakarlistor" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Torrentfilen finns redan i Deluge. Vill du sammanfoga bevakarlistorna?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Inställningar för Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Fråga varje gång var filerna ska sparas" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Välj en mapp" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Lagra alla torrent filer i:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Spara alla hämtningar i:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Hämtningsplats" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Ladda automatiskt ner alla torrents till:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Ladda automatiskt" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Antal aktiva torrent-filer som Deluge ska köra. Ställ in -1 för obegränsat " -"antal." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Maximalt antal samtidigt aktiva torrent-filer:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Aktivera filval för torrent-filer före inläsning" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Visa endast om torrenten innehåller mer än en fil" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Prioritera första och sista delarna av filer i torrent" - -#: glade/preferences_dialog.glade:335 -#, fuzzy -msgid "Start torrents in paused state" -msgstr "Starta torrents i pausat läge" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrent-filer" - -#: glade/preferences_dialog.glade:390 -#, fuzzy -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Full allokering förallokerar allt utrymme som behövs för torrenten och " -"förhindrar därigenom datafragmentering på disken" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Använd full allokering" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Kompakt allokering allokerar bara utrymme vid behov" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Använd kompakt allokering" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Allokering" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Hämtningar" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Observera - Ändringar i dessa inställningar kommer endast att bli " -"aktiverade nästa gång som Deluge har startats om." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Från:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Till:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge kommer automatiskt att välja en ny port varje gång" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Slumpmässiga portar" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Testa aktiv port" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktiv port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Distribuerad hash-tabell kan förbättra mängden aktiva anslutningar." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Aktivera Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Universal Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT portmappningsprotokoll" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Distributörs utbyte" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Lokal distributörsutforskning" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Extra nätverksinställningar" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Inkommande:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Inaktiverad\n" -"Aktiverad\n" -"Tvingad" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Utgående:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Föredra att kryptera hela dataströmmen" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Nivå:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Handskakning\n" -"Full ström\n" -"Båda" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Kryptering" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Nätverk" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Kölägg torrent-filer nederst när de börjar distribueras" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Kölägg nya torrent-filer över färdiga" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" -"Stoppa distribuering av torrent-filer när deras utdelningsförhållande når:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Töm automatiskt torrent-filer som når sitt högsta utdelningsförhållande" - -#: glade/preferences_dialog.glade:1105 -#, fuzzy -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Sluta distributera torrents när distributationstiden når:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Antal timmar:" - -#: glade/preferences_dialog.glade:1142 -#, fuzzy -msgid "Automatically clear torrents that reach the max seed time" -msgstr "Ränsa automatiskt torrents som når den maximala distributationstiden" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Distribuering" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Distribuerar" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -#, fuzzy -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Maximalt antal uppkopplingsförsök per sekund. Ett högt värde kan krascha " -"vissa billigare routrar. Ställ in -1 för obegränsat." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Max antal uppkopligsförsök per sekund." - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Maximalt antal sändningsplatser för alla torrent-filer. Ange -1 för " -"obegränsat antal." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maximal sändningshastighet för alla torrent-filer. Ställ in -1 för " -"obegränsad." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Maximal hämtningshastighet för alla torrent-filer. Ange -1 för obegränsad." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maximal hämtningshastighet (Kibyte/s)" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" -"Maximalt antal tillåtna anslutningar. Ställ in till -1 för obegränsat antal." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Maximalt antal anslutningar:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maximal sändningshastighet (Kibyte/s)" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Maximalt antal sändningsplatser:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Maximala antalet halvt öppna anslutningar. En hög siffra kan krascha billiga " -"routrar. Sätt värde -1 för oändligt." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Maximalt antal halvt öppna anslutningar:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Allmän bredbandsanvändning" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Maximalt antal sändningsplatser per torrent-fil. Ange -1 för obegränsat " -"antal." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Maximalt antal anslutningar per torrent-fil. Ange -1 för obegränsat antal." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Bredbandsanvändning per torrent-fil" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Bandbredd" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Påverkar vanliga bittorrent-klienter" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "Klientproxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Server" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Ingen\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 med inloggning\n" -"HTTP\n" -"HTTP med inloggning" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Lösenord" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Användarnamn" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxy-typ" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "Klientproxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Bevakarproxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Bevakarproxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT-proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT-proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Webbdistribueringsproxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Webbdistribueringsproxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxyservrar" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Aktivera ikon i systembrickan" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Minimera till systembrickan vid stängning" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Starta minimerat till systembricka" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Lösenordsskydda systembrickan" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Lösenord:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Systembricka" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "Använd avancerad status rad (kräver lite mer CPU/RAM)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Detaljerad Status Rad" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge kommer att kolla med våra servrar och notifiera dig om det finns en " -"nyare version tillgänglig" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Bli notifierad om nya versioner" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Uppdateringar" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Hjälp oss förbättra Deluge genom att skicka oss dina Python- och PyGTK-\n" -"versioner, operativsystem samt processortyper. Absolut ingen annan\n" -"information skickas." - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Systeminformation" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Övriga" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Tvinga Återkoll" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Å_teruppta" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Paus" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Ta bort torrent-fil" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Bevakarinställningar" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Uppdatera bevakare" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Redigera bevakare" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_Skrapa Tracker" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Kö" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Överst" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Uppåt" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Nedåt" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Nederst" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Öppna behållande mapp" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Visa Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Återuppta alla" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Pausa alla" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Hastighetsgräns för _hämtning" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Hastighetsgräns för _sändning" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Avsluta" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Redigera bevakare" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Bevakarredigering" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge filväljare" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" -"Torrent-filen kommer inte att distribueras via det bevakarlösa nätverket " -"(DHT)." - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Ställ in privatflaggan" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Förstagångskonfigurering" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Denna guide kommer hjälpa dig att anpassa Deluges inställningar efter dina " -"behov. Om du inte använt Deluge förut bör du notera att många funktioner i " -"Deluge kommer i form av insticksmoduler, som kan kommas åt genom att klicka " -"på Insticksmoduler i Redigera-menyn eller verktygsfältet." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge behöver ett omfång portar att lyssna efter inkommande anslutningar " -"på. BitTorrents standardportar är 6881-6889, men många internetleverantörer " -"blockerar dessa portar så det rekommenderas att du väljer andra, förslagsvis " -"mellan 49152 och 65535. Alternativt kan du låta Deluge välja portarna " -"slumpmässigt." - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Använd s_lumpmässiga portar" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Vill du att Deluge automatiskt hämtar ner till en förvald plats, eller vill " -"du välja var filerna skall sparas varje gång?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Fråga var varje fil ska sparas" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Spara alla hämtningar i: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Välj sändningshastighet för din anslutning, vilket vi kommer att använda för " -"att automatiskt skapa inställningsförslag nedan" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maximalt antal aktiva torrentfiler:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Din sändningshastighet:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"_Hjälp oss att förbättra Deluge genom att skicka in era Python och PyGTK\n" -"versioner, OS och processortyp. Absolut ingen annan\n" -"information kommer skickas." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/s" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Obegränsad" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Aktiverad" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Annan..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Hämtningshastighet (KiB/s)" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Sändningshastighet (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge är låst" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge är lösenordsskyddat.\n" -"Ange ditt lösenord för att visa Deluge-fönstret." - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Oändligt" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Okänd" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Namn" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Tid kvar" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Tillg." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Förhållande" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Ta bort den gamla torrentkällan?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Pausad %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Köad %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Det finns en ny version av Deluge. Vill du besöka hämtningswebbsidan?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Anslutningar" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Hämtning" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Sändning" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "BitTorrent-klienten Deluge" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Välj en hämtningsmapp" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Ett fel inträffade vid försök att lägga till torrent-filen. Det är möjligt " -"att din torrent-fil är skadad." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Okänt torrent-dublettfel." - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" -"Det finns inte tillräkligt med diskutrymme för att ladda ner hela filen." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Utrymme som behövs:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Tillgängligt utrymme:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Lägg till torrent-fil från webbadress" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Ange webbadressen till torrent-filen som ska hämtas" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" -"Varning - alla hämtade filer för denna torrent-fil kommer att tas bort!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Är du säker på att du vill tabort alla distribuerade torrenter?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Köad" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Kontrollerar" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Ansluter" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Hämtar metadata" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Hämtar" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Färdig" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Allokerar" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "behövda bytes" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" -"Det finns inte tillräckligt med ledigt diskutrymme för att färdigställa din " -"hämtning." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Annonsering skickad" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Annonsering ok" - -#: src/core.py:774 -msgid "Alert" -msgstr "Varning" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP-kod" - -#: src/core.py:776 -msgid "times in a row" -msgstr "gånger i rad" - -#: src/core.py:788 -msgid "Warning" -msgstr "Varning" - -#: src/files.py:77 -msgid "Filename" -msgstr "Filnamn" - -#: src/files.py:82 -msgid "Priority" -msgstr "Prioritet" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"Filprioritet kan bara ställas in när full allokering används.\n" -"Stäng av kompakt allokering i inställningarna, ta sedan bort den här torrent-" -"filen och lägg till den på nytt." - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Insticksmodul" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Aktiverad" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Välj en torrent-fil" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent-filer" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Alla filer" - -#: src/common.py:88 -msgid "KiB" -msgstr "Kibyte" - -#: src/common.py:91 -msgid "MiB" -msgstr "Mibyte" - -#: src/common.py:94 -msgid "GiB" -msgstr "Gibyte" - -#: src/common.py:97 -msgid "TiB" -msgstr "Tibyte" - -#: src/common.py:99 -msgid "PiB" -msgstr "Pibyte" - -#: src/common.py:206 -msgid "External command" -msgstr "Externt kommando" - -#: src/common.py:207 -msgid "not found" -msgstr "hittades inte" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"Ladda ned och importera blockeringslistor över IP-adresser.\n" -"\n" -"I nuläget hanterar denna insticksmodul PeerGuardian- (binär och text),\n" -"SafePeer- och Emule-listor. PeerGuardian 7zip-formatfiler stöds inte.\n" -"Filer kan skrivas in som webbadresser eller platser i det lokala\n" -"filsystemet.\n" -"\n" -"En sida som pekar ut hämtningsplatser för blockingslistor finns på\n" -"wikin:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian-text (Okomprimerad)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP-lista (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer-text (zippad)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Kunde inte hämta webbadress" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Kunde inte öppna blockeringslistfil" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -#, fuzzy -msgid "Wrong file type or corrupted blocklist file." -msgstr "Fel filtyp eller trasiga filer" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Importerad" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP-adress" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blockeringslista" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "poster" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Webbadress till blockeringslista" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "dagar" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Läser in och installerar blockeringslista" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Importerar" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Färdig" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Fick formatundantag för zipfil:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -#, fuzzy -msgid "Invalid leader" -msgstr "Ogiltig ledare" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Felaktig magisk kod" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Felaktig version" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Sätt önskat utdelningsförhållande för en torrent-fil" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Önskad Ratio" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Inte satt" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Inte satt" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Önskat utdelningsförhållande" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Detta insticksprogram visar de parter och distributörer som deltar i " -"respektive torrent samt deras ip, land, klient, hur mycket de laddat ner och " -"upp- och nedladdningshastighet.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP-adress" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Klient" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Procent färdig" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrentskapare" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Denna torrent-fil kommer att skapas från en fil" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Fil:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Denna torrent-fil kommer att skapas från en katalog" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Mapp:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Källa" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Spara torrent-fil som:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Läs in torrent-fil i Deluge för distribuering." - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Lägg till torrent-fil till kö" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent-fil" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Bevakare" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Nät Distributörer" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Kommentarer" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Skapare" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Sätt Privat Flagga" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Överföringen blir effektivare ju mindre storleken på delarna är, men torrent-" -"filen blir större." - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Delstorlek:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Avancerad" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "En insticksmodul för att skapa torrent-filer" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Ny Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Ny Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Skapa ny torrent" - -#: plugins/TorrentCreator/__init__.py:99 -#, fuzzy -msgid "Save file as..." -msgstr "Spara fil som..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Du måste välja en källa för torrent" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Välj fil som torrent-filen ska sparas som." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Inställningar för Torrent-notifieringar" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "Aktivera händelseljud (kräver pygame, inte tillgängligt i Win32)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Slå på blinkade ikon i systembrickan" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Aktivera popupmeddelande (kräver python-notify, inte tillgängligt i Win32)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Få ikonen i systembrickan att blinka när en torrent-fil hämtats " -"och/ellervisa en notifiering" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent-fil färdig" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Instickmodul för övervakning av nätverkshälsa\n" -"\n" -"Skriven av Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Hälsa: ok]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Inställningar för händelseloggning" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Aktivera loggfiler" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Loggfiler" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Part blockerad" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Block färdigt" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Block under nedladdning" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Del klar" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -#, fuzzy -msgid "Storage moved" -msgstr "Förvaring flyttad" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Tracker varning" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Tracker varning" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Bevakarsvar" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Bevakarannonsering" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -#, fuzzy -msgid "Fastresume rejected error" -msgstr "Snabbåterhämtningsfel" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "Partbannlysningsfel" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Hashningsfel" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Filfel" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Ogiltig begäran" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "Partmeddelanden" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent-fil färdig" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Välj händelser som ska loggas" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"Lägger till en flik med loggning av valda händelser.\n" -"\n" -"Händelsemeddelanden skapas av libtorrent-varning.\n" -"Om du vill att de strängarna ska övesättas till ditt språk\n" -"rapportera problemet till libtorrent, inte Deluge.\n" -"\n" -"Angående loggningsfilerna så sparas de i en loggningsmapp\n" -"i Deluges konfigurationsmapp. Händelsemeddelanden for enskilda\n" -"torrent-filer sparas till induviduella loggfiler med samma namn som\n" -"tillhörande torrent-fil. Händelsemeddelanden som inte är kopplade\n" -"till någon torrent-fil sparas i loggfiler namngivna efter händelsen\n" -"(till exempel peer_messages.log).\n" -"Händelsemeddelanden i loggfiler har också en tidsstämpel.\n" -"Användaren är ansvarig för att städa bland loggarna.\n" -"\n" -"Från och med version 0.2\n" -"Händelser, men inte loggfiler, kapas vid visningen.\n" -"Nya händelser vissas högst upp.\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Händelselogg" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "Händelsemeddelande: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Partmeddelande" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "IP-adress: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "klient: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -#, fuzzy -msgid "piece index: " -msgstr "delindex: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "statuskod: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "Antal i följd: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "Blockera index: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "parthastighet " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Sätt önskad hastighetsbegränsning för varje torrent-fil." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrent-_hämtningshastighet" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrent-_sändningshastighet" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrent-sändningshastighet (Kibyte/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrent-hämtningshastighet (Kibyte/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Insticksmodul för nätverksaktivitetsgraf\n" -"\n" -"Skriven av Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "Graf" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "Förlopp" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Det uppstod ett fel när filen skulle köras." - -#: plugins/TorrentFiles/__init__.py:34 -#, fuzzy -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"Detta insticksprogram visar filerna i en torrent och låter dig sätta " -"prioritet på dem och välja vilka du vill eller inte vill ladda ner.\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Filer" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Flytta torrent" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "_Byt Torrentkälla" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Välj en mapp att flytta filer till" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Flytta färdiga hämtningar till:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "Avbryt" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "OK" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Denna plugin gör det möjligt att lägga till en webb distribution i torrent " -"filen" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "_Lägg till webb distribution" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "Lägg till Web Seed" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "Webbadress:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Nerladdningsgräns" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Uppladningsgräns" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Aktiva torrents:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "Sändningsplatser:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Maximala Anslutningar" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Kalenderinställningar" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" -"Grön är de höga gränserna, gula de låga gränserna och röd betyder stoppad." - -#: plugins/Scheduler/plugin.py:180 -#, fuzzy -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Om en begränsning är satt till -1, är den obegränsad." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Konfiguration av WebUi" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Port Nummer" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Nytt Lösenord" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Nytt Lösenord(bekräfta)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Mall" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Knapp Stil" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Text och bild" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Endast Bild" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Endast Text" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "Bekräftat lösenord <> Nytt lösenord\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "översätt någonting" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "Välj en url eller en torrent, inte båda." - -#: plugins/WebUi/deluge_webserver.py:203 -#, fuzzy -msgid "no data." -msgstr "ingen data." - -#: plugins/WebUi/deluge_webserver.py:304 -#, fuzzy -msgid "refresh must be > 0" -msgstr "uppdatering måste vara > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# Av Filer" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Om" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Lägg till torrent" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Verkställ" - -#: plugins/WebUi/scripts/template_strings.py:7 -#, fuzzy -msgid "Auto refresh:" -msgstr "Autouppdatering:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Konfigurera" - -#: plugins/WebUi/scripts/template_strings.py:12 -#, fuzzy -msgid "Debug:Data Dump" -msgstr "Felsökning: Data Dumpning" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Ta bort nedladdade filer." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Inaktivera" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "Nedladdat" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Aktivera" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Fel" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "Eta" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "Logga in" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "Logga ut" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "Nästa annonsering" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Av" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Lösenordet är ogiltig, försök igen." - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Pausa alla" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Delar" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Kön Nere" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "Köposition" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Återannonsera" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Läs om sidan varje:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "Ta bort torrent" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Återstarta alla" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "Ange" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Hastighet:" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Starta" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Skicka" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrent lista" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Sammanlagd storlek" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Trackerstatus" - -#: plugins/WebUi/scripts/template_strings.py:62 -#, fuzzy -msgid "Upload torrent" -msgstr "Ladda upp torrent" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Uppladdat" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Url" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "sekunder" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -#, fuzzy -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" -"Flödet kommer att hämtas automatiskt, baserat på uppdateringsintervallet." - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Flödet måste uppdateras automatiskt." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Inaktiverad" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Updatera Intervall" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "Webbadress" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Flöden" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Typ" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Flöde" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Information" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Mönster" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Från" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Säsong" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Episod" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Genom" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Matchar inte" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "År" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Månad" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Dag" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Sätt status till pausad." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Hämta" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "Ersättning" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Mönster" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge standard" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" -"Innehållet kommer automatiskt att laddas ner till specifierad katalog." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Välj:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Utmatning" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filter" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Visa en FlexRSS-ikon på Deluge's verktygsfält." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Visa knapp på verktygsfältet." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Gränssnitt" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -#, fuzzy -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" -"Matningen kommer att hämtas och tolkas i sina egna trådar. Applikationen " -"kommer inte att blockeras, men det kan vara opålitligt." - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Trådad (experimental)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "Matningshämtning" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Domän" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Sökväg" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Värde" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Kakor" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Konfiguration" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Hantera sökinsticksmoduler" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Namn:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Lägg till sökmotor genom att ange namn och webbadress. Som namn skrivs " -"namnet på sökmotorn som ska användas. Som webbadress skrivs adressen till " -"söksidan. Användarens sökning kommer att stå i stället för ${query} i " -"webbadressen.\n" -"Till exempel skulle en Google-sökning bli:\n" -"Namn: Google\n" -"UL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Hjälp" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Sök efter torrents anonymt" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Söksträng" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Välj motor" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Hantera motorer" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Sök " diff --git a/po/ta.po b/po/ta.po deleted file mode 100644 index 3d76042a6..000000000 --- a/po/ta.po +++ /dev/null @@ -1,2388 +0,0 @@ -# Tamil translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2007-12-05 13:56+0000\n" -"Last-Translator: viki \n" -"Language-Team: Tamil \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "டோர்றேன்ட் ஐ சேர்க்கவும்" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "சேர்க்கவும்" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "டோர்றேன்ட் ஐ நீக்கவும்" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "நீக்கவும்" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "சீடிங் டோர்றேன்ட் - களை காலியாக்கு" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "காலியாக்கு" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "டோர்றேன்ட் ஐ துவக்க / மீண்டும் துவக்க" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "மீண்டும் துவக்க" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "டோர்றேன்ட் ஐ தற்காலிகமாக நிறுத்துக" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "தற்காலிகமாக நிறுத்து" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "டோர்றேன்ட் - களை மேல் நோக்கி வரிசைப்படுத்துக" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "மேல்" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "டோர்றேன்ட் - களை கீழ் நோக்கி வரிசைப்படுத்துக" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "கீழ்" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "ட்டிலுஜ் விருப்பங்களை மாற்றுக" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "விருப்பங்கள்" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "சொருகுபொருள்கள்" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "கோப்பு (_F)" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_டோர்றேன்ட் ஐ சேர்க்கவும்" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "யு ஆர் எல் - ஐ சேர்க்கவும்" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_முடித்தவற்றை காலியாக்குக" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "(_E)திருத்து" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "தகுதி" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_உதவி" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "துண்டுகள்:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "பெயர்:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "காட்டு/மறை" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "டெலூஜ் விருப்பத் தேர்வுகள்" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "பதிவிறக்கங்கள்" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "வலையமைப்பு" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "விதைத்தல்" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "கடவுச்சொல்:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "ஏனையவை" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "தெரியாதவை" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "பெயர்" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "இணைப்புகள்" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "டெலூஜ் பிட்டாரெண்ட் வாங்கி" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "ஐபி முகவரிகள்" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "வாங்கி" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "முடிக்கப்பட்ட விகிதம்" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "முன்னேற்றம்" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "கோப்புக்கள்" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "தொடங்கு" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/th.po b/po/th.po deleted file mode 100644 index 678232ac1..000000000 --- a/po/th.po +++ /dev/null @@ -1,2388 +0,0 @@ -# Thai translation for deluge -# Copyright (c) 2008 Rosetta Contributors and Canonical Ltd 2008 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2008. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-05-09 22:31+0000\n" -"Last-Translator: DevilDogTG \n" -"Language-Team: Thai \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "เพิ่มงาน" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "เพิ่มงาน" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "ลบงาน" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "ลบงาน" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "ลบงานที่โหลดเสร็จแล้ว" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "ลบงานที่โหลดเสร็จแล้ว" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "เริ่มงาน/ทำงานต่อ" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "ทำงานต่อ" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "พักงาน" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "พักงาน" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "เพิ่มงานจากลิ้งค์" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/tl.po b/po/tl.po deleted file mode 100644 index 82211a72f..000000000 --- a/po/tl.po +++ /dev/null @@ -1,2388 +0,0 @@ -# Tagalog translation for deluge -# Copyright (c) 2008 Rosetta Contributors and Canonical Ltd 2008 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2008. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-02-04 21:25+0000\n" -"Last-Translator: b3rx \n" -"Language-Team: Tagalog \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Magdagdag ng Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Magdagdag" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Tanggalin ang Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Umpisahan o Ipagpatulog ang Torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Ipagpatuloy" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/tlh.po b/po/tlh.po deleted file mode 100644 index 61f053e0e..000000000 --- a/po/tlh.po +++ /dev/null @@ -1,2388 +0,0 @@ -# Klingon; tlhIngan-Hol translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2007-06-05 19:39+0000\n" -"Last-Translator: Joe Anderson \n" -"Language-Team: Klingon; tlhIngan-Hol \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "noch:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Dotlhvam noch:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "" - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/tr.po b/po/tr.po deleted file mode 100644 index c9eb763c4..000000000 --- a/po/tr.po +++ /dev/null @@ -1,2578 +0,0 @@ -# Turkish translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-27 01:18+0000\n" -"Last-Translator: webdr \n" -"Language-Team: Turkish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Torrent Ekle" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Ekle" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Torrent Kaldır" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Kaldır" - -#: glade/delugegtk.glade:56 -#, fuzzy -msgid "Clear Seeding Torrents" -msgstr "Gönderilen Torrentleri Temizle" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Temizle" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Torrenti Başlat yada Devam Et" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Devam et" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Torrenti Duraklat" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Duraklat" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Sıradaki Torrent Yukarı" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Yukarı" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Sıradaki Torrent Aşağı" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Aşağı" - -#: glade/delugegtk.glade:142 -#, fuzzy -msgid "Change Deluge preferences" -msgstr "Deluge tercihlerini değiştir" - -#: glade/delugegtk.glade:143 -#, fuzzy -msgid "Preferences" -msgstr "Tercihler" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Eklentiler" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Dosya" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "Torrent _Ekle" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "_URL Ekle" - -#: glade/delugegtk.glade:216 -#, fuzzy -msgid "_Clear Completed" -msgstr "Tamamlananları _Sil" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Düzenle" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "E_klentiler" - -#: glade/delugegtk.glade:302 -#, fuzzy -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Görünüm" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "Araç _Çubuğu" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Ayrıntılar" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Sütunlar" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Boyut" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Durum" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Kaynaklar" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Eşler" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "İndirme Hızı" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Gönderme Hızı" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Kalan Süre" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Erişilebilirlik" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Paylaşım Oranı" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Yardım" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Deluge Gelişimine Bağışta Bulun" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Bağış Yap" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Anasayfa" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_SSS" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Topluluk" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Bu uygulamanın dilinize çevrilmesine yardımcı olun" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "Bu Uygulamayı _Çevir..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "İlk kullanım yapılandırma sihirbazını çalıştırır" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "Yapılandırma _Sihirbazını Çalıştır" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "İndirilen:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Gönderilen:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Kaynaklar:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Paylaşım Oranı:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Hız:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Eşler:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "Tahmini Kalan Süre" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Parçalar:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Erişilebilirlik:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "İstatistikler" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Dosya sayısı:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Toplam Boyut:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "İzleyici:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "İzleyici Durumu:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Sonraki Duyuru:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Ad:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Yol:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Torrent Bilgisi" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Detaylar" - -#: glade/dgtkpopups.glade:42 -#, fuzzy -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Seçili torrent(ler)i Deluge'den silmek istediğinize " -"emin misiniz?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "İndirilmiş dosyaları sil" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr ".torrent dosyasını sil" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Göster/Gizle" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Torrent Ekle..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Bitenleri Temizle" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "Dosya _Aç" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Tümünü Seç" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Tüm Seçimleri Tersine Çevir" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "İndirme" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Normal" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Yüksek" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "En yüksek" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge İzleyici Listesine Dahil Et" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "Torrent Deluge de mevcut, izleyici listesine dahil edilsinmi?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge Seçenekleri" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Her İndirlenin Nereye Kaydedileceğni Sor" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Bir Klasör Seç" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Bütün torrent dosyalarını buraya kaydet:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Bütün indirilenleri buraya sakla:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "İndirme Yeri" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Tüm torrent dosyalarını buradan otomatik yükle:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Otomatik Yğkleme" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Deluge indirecegi aktif torrent sayısını girin.Sınırsız için -1 yazınız." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Aktif torrentte maksimum eş:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Torrenti indirmeye başlamadan önce dosya seçimine izin ver" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Torrent bir dosyadan fazla ise sadece göster" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "İlk ve son parçalara öncelik ver" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Torrenti Kaldığı yerden devam ettir." - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrentler" - -#: glade/preferences_dialog.glade:390 -#, fuzzy -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Tam alan tahsisi torrent için gerekli disk alanının tamamını önceden ayırır " -"ve disk parçalanmasını engeller" - -#: glade/preferences_dialog.glade:391 -#, fuzzy -msgid "Use Full Allocation" -msgstr "Tam alan tahsisi yap" - -#: glade/preferences_dialog.glade:413 -#, fuzzy -msgid "Compact allocation only allocates space as needed" -msgstr "Yoğun alan tahsisi sadece ihtiyaç kadar disk alanı ayırır" - -#: glade/preferences_dialog.glade:414 -#, fuzzy -msgid "Use Compact Allocation" -msgstr "Yoğun alan tahsisi yap" - -#: glade/preferences_dialog.glade:434 -#, fuzzy -msgid "Allocation" -msgstr "Alan tahsisi" - -#: glade/preferences_dialog.glade:458 -#, fuzzy -msgid "Downloads" -msgstr "İndirilenler" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Lütfen Dikkat- Bu ayarlardaki değişiklikler Deluge yeniden " -"başlatıldığında etkin hale gelecektir." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Gönderen:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Alıcı:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge her zaman otomatik olarak farklı bir port kullansın." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Rastgale Ports" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Aktif Portu Test Et" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Aktif Port:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -#, fuzzy -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Dağıtılmış yığın tablosu aktif bağlantı sayısını artırabilir" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Anahat DHT Etkinleştir" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "Genel Tak ve Çalıştır" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT Port Haritalama Protokolü" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Eş değişimi" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "Yerel Dağıtımcı Araştırması" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "Ağ için Ekstralar" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Gelen:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Kapalı\n" -"Açık\n" -"Zorunlu" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Giden:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Tüm aktarımı şifrelemeyi tercih et" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Seviye:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"Elsıkışma\n" -"Tamamı bağlı\n" -"İkisinden biri" - -#: glade/preferences_dialog.glade:954 -#, fuzzy -msgid "Encryption" -msgstr "Şifreleme" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Ağ" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "İndirilmesi bitmiş torrentler gönderime başlayınca en alta taşı" - -#: glade/preferences_dialog.glade:1037 -#, fuzzy -msgid "Queue new torrents above completed ones" -msgstr "Yeni torrentleri tamamlanan indirilenlerin üzerinde sırala" - -#: glade/preferences_dialog.glade:1053 -#, fuzzy -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Paylaşım oranına ulaşınca torrentleri durdur:" - -#: glade/preferences_dialog.glade:1089 -#, fuzzy -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Azami paylaşım oranına ulaşınca torrentleri temizle" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Dağıtma zamanı aşıldığında torrent dağıtımını durdur:" - -#: glade/preferences_dialog.glade:1120 -#, fuzzy -msgid "Number of hours" -msgstr "Saatlerin sayısı" - -#: glade/preferences_dialog.glade:1142 -#, fuzzy -msgid "Automatically clear torrents that reach the max seed time" -msgstr "Maksimum gönderim süresine ulaşan dosyaları otomatik temizle." - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Gönderiliyor" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Kaynak/Gönderiliyor" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -#, fuzzy -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Saniyede denenecek maksimum bağlantı sayısı.Yüksek değerler Routers ınızda " -"bozulmalar meydana getirebilir. Sınırsız için -1 yazınız." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Saniyede Denenecek Maksimum Bağlantı Sayısı:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Bütün torrent ler için maksimum gönderim slotu. Sınırsız için -1 yazınız." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Bütün torrentler için maksimum gönderim hızı. Sınırsız için -1 yazınız." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Bütün torrentler için maksimum indirme hızı. Sınırsız için -1 yazınız." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Maksimum İndirme Hızı (KB/sn)" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" -"İzin Verilen En Çok Bağlantı Sayısı. Sınırsız Olması İçin -1 Olarak " -"Ayarlayın." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "En Çok Bağlantı" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Maksimum Gönderme Hızı (KB/sn)" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -#, fuzzy -msgid "Maximum Upload Slots:" -msgstr "Azami Gönderme Yuvası:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" -"Maksimum yarı-açık bağlantılar.Yüksek bir değer router inize zarar " -"verebilir.Limitsiz için -1 yazınız." - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -#, fuzzy -msgid "Maximum Half-Open Connections:" -msgstr "Azami Yarım-Açık Bağlantı:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Genel Bantgenişliği Kullanımı" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -#, fuzzy -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" -"Torrent başına açılacak Maksimum upload Slotu. Sınırsız için -1 yazınız." - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Torrent başına yapılacak Maksimum bağlantı sayısı. Sınırsız için -1 yazınız." - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "Bir torrentin Bantgenişliği Kullanımı" - -#: glade/preferences_dialog.glade:1573 -#, fuzzy -msgid "Bandwidth" -msgstr "Bantgenişliği" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "Sıradan bittorrent bağlantılarını etkiler" - -#: glade/preferences_dialog.glade:1620 -#, fuzzy -msgid "Peer Proxy" -msgstr "Paylaşımcı Vekil Sunucusu" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Port" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Sunucu" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Hiçbiri\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -#, fuzzy -msgid "Password" -msgstr "Şifre" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Kullanıcı Adı" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -#, fuzzy -msgid "Proxy type" -msgstr "Vekil Sunucu tipi" - -#: glade/preferences_dialog.glade:1782 -#, fuzzy -msgid "Peer Proxy" -msgstr "Eş Proxy" - -#: glade/preferences_dialog.glade:1815 -#, fuzzy -msgid "Tracker Proxy" -msgstr "İzleyici için Proxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "İzleyici Proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT Vekil Sunucusu" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Vekil Sunucusu" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -#, fuzzy -msgid "Proxies" -msgstr "Vekil sunucular" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Sistem tepsisi simgesini etkinleştir" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Kapattığımda simge durumuna küçült" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Görev çubuğunda başlat" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Sistem çekmecesi şifre koruması" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Parola:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Sistem Çekmecesi" - -#: glade/preferences_dialog.glade:2582 -#, fuzzy -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" -"Gelişmiş ilerleme çubuğunu kullan (Normalden fazla İşlemci/Bellek kullanır)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "Ayrıntılı İlerleme Çubuğu" - -#: glade/preferences_dialog.glade:2627 -#, fuzzy -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge sunucuları kontrol ederek yeni versiyon çıktığında size bildirecek" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Yeni sürüm hakkında beni uyar" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Güncellemeler" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Python ve PyGTK sürümünüz, işletim sisteminiz ve işlemci türünüze ait " -"bilgileri bize göndererek Deluge'u geliştirmemize yardımcı olun" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Sistem Bilgisi" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Diğer" - -#: glade/torrent_menu.glade:11 -#, fuzzy -msgid "_Force Recheck" -msgstr "_Yeniden Denetlemeye Zorla" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "De_vam" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Duraksat" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Torrenti Kaldır" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_İzleyici Tercihleri" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_İzleyiciyi güncelle" - -#: glade/torrent_menu.glade:121 -#, fuzzy -msgid "_Edit Trackers" -msgstr "_İzleyiciyi Düzenle" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "_İzleyici Kaldır" - -#: glade/torrent_menu.glade:164 -#, fuzzy -msgid "_Queue" -msgstr "_Sıralama" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "Ü_st" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Yukarı" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Aşağı" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Alt" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_İçerdiği Klasörü Aç" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Deluge Göster" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Tümüne Devam Et" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "_Tümünü Duraksat" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_İndirme Hız Limiti" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "_Gönderme Hız Limiti" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "Çık" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "İzleyicileri Düzenle" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "İzleyici Düzenlemesi" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge Dosya Seçimi" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Torrent dosyası izleyicisiz ağlar (DTH) üzerinden dağıtılmayacak" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Özel bayrağınızı belirleyin" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "İlk çalıştırma yapılandırması" - -#: glade/wizard.glade:20 -#, fuzzy -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Bu sihirbaz Deluge'yi istediğiniz gibi yapılandırmanıza yardım edecek. Eğer " -"Deluge'de yeniyseniz şunu unutmayın ki, Deluge'nin işlevselliğini ve " -"özelliklerini büyük ölçüde Eklentiler sağlar." - -#: glade/wizard.glade:36 -#, fuzzy -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge dışarıdan gelen bağlantıları beklemek için bir port aralığına ihtiyaç " -"duyar. Bittorent için önceden belirlenen portlar 6881-6889 aralığıdır. Ancak " -"bir çok ISP bu portları blokladığı için 49152 ile 65535 aralığında kendinize " -"yeni portlar seçmenizi öneririz. Bunun dışında, Deluge'nin sizin için her " -"seferinde rastgele port seçmesini de sağlayabilirsiniz." - -#: glade/wizard.glade:88 -#, fuzzy -msgid "Use _Random Ports" -msgstr "Rastgele port" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Deluge indirilen dosyaları öntanımlı bir klasöre mi kaydetsin ya da her " -"seferinde indirilecek konumu siz mi seçmek istersiniz?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Her dosyayı nereye kaydedeceğini sorsun" - -#: glade/wizard.glade:165 -#, fuzzy -msgid "Store all downloads in: " -msgstr "İndirilen bütün dosyaların saklanacağı dizin: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Lütfen buradan upload hızınızı seçin ve böylece aşağıda size otomatik " -"öneriler sunulacaktır" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Maksimum Aktif Torrent Sayısı:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "Gönderim Hızınız:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"Deluge gelişiminde bize yardımcı olabilirsiniz. Bunun için:\n" -"Python ve PyGTK sürümünüzü, işletim sistemi\n" -"ve işlemci türünüzü bize yollayabilirsiniz. Kesinlikle\n" -"başka bir bilgi gönderilmeyecektir." - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KB/sn" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Sınırsız" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Etkinleştirildi" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Diğer..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "İndirme Hızı (KB/sn):" - -#: src/interface.py:419 -#, fuzzy -msgid "Upload Speed (KiB/s):" -msgstr "" -"Gönderim Hızı (KB/sn): \n" -"Gönderme Hızı (KB/sn):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge Kilitli" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge şifre ile Korunmakta.\n" -"Deluge Penceresini açmak için, lütfen şifrenizi giriniz" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Sonsuzluk" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Bilinmeyen" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "İsim" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "Kalan Süre" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Oran" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Oran" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "Eski torrent kaynağı silinsin mi?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Duraksatıldı %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "Kuyrukta %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" -"Deluge daha yeni bir sürüme güncellenebilir. İndirme sayfamızı görmek ister " -"misiniz?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "Bağlantılar" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "İndir" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Gönder" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge Bittorrent İstemcisi" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Bir indirme dizini seçin" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" -"Torrent eklenmeye çalışılırken bir hata oldu. Muhtemelen .torrent dosyanız " -"bozulmuş." - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "Bilinmeyen Eş hatası" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "İndirdiğiniz veriyi tamamlayabilmek için yeterli disk alanı yok." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Bu kadar Alan Gerekli:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Kullanılabilir Alan:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "URL'den torrent ekle" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "İndireceğiniz .torrent'in URL'sini girin" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Uyarı - Bu torrente ait indirilen dosyaların tümü silinecek!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Paylaşılan bütün torrent leri kaldırmak istediğinizden eminmisiniz." - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "Sıraya Eklendi" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Denetleniyor" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "Bağlanıyor" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Metadata İndiriliyor" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "İndiriliyor" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Tamamlandı" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "Ayrılıyor" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "bytes gerekli" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "İndirme işinizi tamamlamak için yeterli disk alanı yok." - -#: src/core.py:761 -msgid "Announce sent" -msgstr "Duyuru gönder" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "Duyuru TAMAM" - -#: src/core.py:774 -msgid "Alert" -msgstr "Uyarı" - -#: src/core.py:775 -#, fuzzy -msgid "HTTP code" -msgstr "HTTP kodu" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "Uyarı" - -#: src/files.py:77 -msgid "Filename" -msgstr "Dosya adı" - -#: src/files.py:82 -msgid "Priority" -msgstr "Öncelik" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Eklenti" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Etkin" - -#: src/dialogs.py:445 -#, fuzzy -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge özgür yazılımdır, Free Software Foundation\n" -"tarafınca yayınlanmış GNU Genel Kamu Lisansı ikinci\n" -"sürüm ya da (seçiminize istinaden) sonraki bir sürüm\n" -"şartlarınca değiştirilebilir ve dağıtılabilir. Deluge\n" -"kullanışlı olması maksadıyla dağıtılmaktadır, ancak\n" -"HİÇBİR GARANTİSİ YOKTUR; aynı zamanda BİR AMACA\n" -"UYGUNLUĞU ya da SATILABİLİRLİĞİ garanti etmez.\n" -"Daha fazla ayrıntı için GNU Genel Kamu Lisansını inceleyin.\n" -"GNU Genel Kamu Lisansı'nın bir kopyasını Deluge ile almış\n" -"olmalısınız; eğer almadıysanız Free Software Foundation,\n" -" Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" -"adresine yazın." - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Bir .torrent dosyası seçin" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Torrent Dosyaları" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Tüm dosyalar" - -#: src/common.py:88 -msgid "KiB" -msgstr "KB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PB" - -#: src/common.py:206 -msgid "External command" -msgstr "Harici komut" - -#: src/common.py:207 -msgid "not found" -msgstr "bulunamadı" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Yazı (Sıkıştırılmamış)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP Listesi (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer Yazı (Sıkıştırılmış)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Adres indirilemiyor" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "Karaliste dosyası açılamıyor" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "Yanlış dosya tipi yada bozuk karaliste dosyası." - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "İçe Aktarılanlar" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IPs" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Karaliste" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "girdi" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Karaliste URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "gün" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "Karaliste yükle ve kur" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "İçe aktarılıyor" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Tamamlandı" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" -"Dosya beklediğimiz gibi Gzip arşivi değil ya da bozulmuş. Lütfen Bloklistesi " -"seçeneklerinizi düzenleyin" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Yanlış yönlendirici" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Yanlış sihir kodu" - -#: plugins/BlocklistImport/peerguardian.py:41 -#, fuzzy -msgid "Invalid version" -msgstr "Geçersiz sürüm" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Torrent için oran belirleyin." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_İstenen Oran" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "_Ayarlanmamış" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Ayarlanmamış" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Geçerli Oran" - -#: plugins/TorrentPeers/__init__.py:34 -#, fuzzy -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Size gösterilecek olan ortak eşlerin IP si, ve buna göre, Ülkesi, Kullandığı " -"istemci, Yüzdelik olarak indirmesi ve göndermesi ve indirme hızları.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP Adresi" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "İstemci:" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Tamamlanma Yüzdesi" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Torrent Oluşturucu" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Bu torrent tek dosya halindedir." - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Dosya:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Bu torrent bir klasör halindedir." - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Dizin:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Kaynak" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Torrenti Farklı Kaydet" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Torrent yayımlanmak için Deluge'ye yükleniyor." - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Kuyruğa yeni torrent ekle" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Torrent Dosyası" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "İzleyiciler" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Ağ Dağıtıcıları" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Yorumlar" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Sahibi" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Özel Bayrak Ver" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KB\n" -"64 KB\n" -"128 KB\n" -"256 KB\n" -"512 KB\n" -"1024 KB\n" -"2048 KB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Parça Boyutu:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Gelişmiş" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Torrent oluşturucu eklenti" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Yeni Torrent" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Yeni Torrent" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Yeni Torrent Oluştur" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Dosyayı farklı kaydet..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Torrent için bir kaynak belirtmelisiniz." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Torrenti farklı kaydetmek için dosya seçmelisiniz." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "Torrent Uyarı Tercihleri" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" -"Olay Seslerini Aç ( pygame gerektirir, bu özellik Windows için " -"bulunmamaktadır.)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Görev Çubuğu Ikon simgesi Aktif" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" -"Açılır pencerede uyarılar aktif (python-notify gerektirir, bu özellik " -"Windows için bulunmamaktadır.)" - -#: plugins/TorrentNotification/__init__.py:22 -#, fuzzy -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" -"Dosya indirme işlemi bittiğinde bilgilendirme penceresi aç veya sistem " -"tepsisinde uyarı göster" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "Torrent tamamlandı" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Ağ Sağlık Durumu eklentisi\n" -"\n" -"YazanKripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Sağlık: TAMAM]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "Olay Raporlama Seçenekleri" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -#, fuzzy -msgid "Enable log files" -msgstr "Günlük dosyalarını etkinleştir" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -#, fuzzy -msgid "Log files" -msgstr "Günlük dosyaları" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "Eş blonlandı" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Blok bitti" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Blok indiriliyor" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Parça bitti" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "Depolama taşındı" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "İzleyici Tehlikesi" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "İzleyici Uyarısı" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "İzleyici Cevabı" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "İzleyici Duyurusu" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Dosya hatası" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Geçersiz talep" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -#, fuzzy -msgid "Peer messages" -msgstr "Paylaşımcı mesajları" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Torrent tamamlandı" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "Log lanacak olayları seçin" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "Olay Günlüğü" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "Olay mesajı: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "torrent: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "Paylaşımcı mesajı" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip adresi: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "istemci: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "parça içeriği: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "durum kodu: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "Engellenen İçerik: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "Eş Hızı: " - -#: plugins/SpeedLimiter/__init__.py:20 -#, fuzzy -msgid "Set the desired speed limit per torrent." -msgstr "Her dosya için yeğlenen hız sınırını belirle" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrent _İndirme Hızı" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrent Gönderme _Hızı" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Torrent Gönderme Hızı (KB/sn):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Torrent İndirme Hızı (KB/sn):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"Ağ Aktivitesi Grafiği eklentisi\n" -"Kripkenstein tarafından yazılmıştır" - -#: plugins/NetworkGraph/__init__.py:91 -#, fuzzy -msgid "Graph" -msgstr "Grafik" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "İlerleme" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "Dosya başlatılırken bir hata oldu." - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "Dosyalar" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "Torrenti _Taşı" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "Taşınacak dosyalar için dizin belirtin" - -#: plugins/MoveTorrent/__init__.py:133 -#, fuzzy -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"Torrenti farklı bir bölüme taşıyamazsınız. Lütfen sistem tercihlerinizi " -"kontrol edin. Torrent dosyalarınız farklı bir klasöre taşıyamazsınız, farklı " -"bir bölüme taşıyabilmeniz için torrent dosyanızın yeniden oluşturulması " -"gereklidir." - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "Tamamlanmış indirmeleri buraya taşı:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-İptal" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-Tamam" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" -"Bu eklenti kullanıcıların torrentlerine web kaynakları eklemelerini sağlar" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "Adres:" - -#: plugins/Scheduler/plugin.py:113 -#, fuzzy -msgid "Download limit:" -msgstr "indirme limiti" - -#: plugins/Scheduler/plugin.py:114 -#, fuzzy -msgid "Upload limit:" -msgstr "gönderme limiti" - -#: plugins/Scheduler/plugin.py:115 -#, fuzzy -msgid "Active torrents:" -msgstr "Aktif torrentler" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "Maksimum Bağlantı" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "Zamanlayıcı Ayarları" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "Yeşil yüksek limit, sarı dürük limit ve kırmızı durdurulmuş" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "Eğer limiti -1 olarak belirtirseniz, Limit koymamış olursunuz." - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Web Arayüzü Ayarları" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "Port Numarası" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Yeni Parola" - -#: plugins/WebUi/__init__.py:204 -#, fuzzy -msgid "New Password(confirm)" -msgstr "" -"Yeni Parola(onayla) \n" -"Yeni Parola(doğrula)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "Şablon" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Buton Stili" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "ÖnBellek Şablonları" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Yazı ve resim" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Sadece Resim" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Sadece Yazı" - -#: plugins/WebUi/__init__.py:262 -#, fuzzy -msgid "Confirmed Password <> New Password\n" -msgstr "Onaylanmış Parola <> Yeni Parola\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "URL adresi yada torrent belirtin, biri yeterli." - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "data yok" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "Tazeleme süresi > 0 olmalıdır" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "Dosya Sayısı" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "Hakkında" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Torrent ekle" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "Uygula" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "Otomatik tazeleme:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "Yapılandırma" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "İndirilmiş dosyaları sil." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "Devre dışı bırak" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "İndirilenler" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "Etkinleştir" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "Hata" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -#, fuzzy -msgid "Login" -msgstr "Giriş" - -#: plugins/WebUi/scripts/template_strings.py:26 -#, fuzzy -msgid "Logout" -msgstr "Çıkış" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "Kapalı" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Geçersiz şifre, tekrar deneyin" - -#: plugins/WebUi/scripts/template_strings.py:33 -#, fuzzy -msgid "Pause all" -msgstr "Hepsini duraklat" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Parçalar" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "Sıra Aşağı" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "Sıra Yukarı" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "Yeniden beyan ediliyor" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "Sayfayı yenile:" - -#: plugins/WebUi/scripts/template_strings.py:44 -#, fuzzy -msgid "Remove torrent" -msgstr "Torrenti kaldır" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Hepsine Devam Et" - -#: plugins/WebUi/scripts/template_strings.py:48 -#, fuzzy -msgid "Set" -msgstr "Ayarla" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "Zamanaşımı belirle" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "Hız" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "Başlat" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "Gönder" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Torrent listesi" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "Toplam Boyut" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "İzleyici" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "İzleyici Durumu" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Torrent Yayımla" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Gönderilenler" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "Adres" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "saniye" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Besleme elle yenilenmeli." - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "Kapalı" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "Güncelleme Aralığı" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "Adres" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Haber Kaynakları" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "Tür" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Haber" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "Bilgi" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "Desenler" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "Gönderen" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "Sezon" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "Bölüm" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "Sınırlama Geçmişi" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Uyuşmuyor" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "Yıl" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "Ay" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "Gün" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Test" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Torrenti sıranın başına koy." - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "Duraksatma Süresi verin." - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "İndir" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -#, fuzzy -msgid "Replacement" -msgstr "Yer değiştir" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "Desen" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -#, fuzzy -msgid "Deluge default" -msgstr "Deluge öntanımlı" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "İçerik otomatik olarak belirlenen dizine indirilecek." - -#: plugins/FlexRSS/FlexRSS.glade:1160 -#, fuzzy -msgid "Choose:" -msgstr "Seç:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "Çıktı" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "Filtreler" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "Deluge araççubuğunda FlexRSS ikonunu göster." - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "Düğmeleri araç çubuğunda göster." - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Arayüz" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Alan Adı" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Yol" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Değer" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Çerezler" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Yapılandırma" - -#: plugins/Search/searchdlg.glade:7 -#, fuzzy -msgid "Manage Search Plugins" -msgstr "Arama Eklentilerini Yönet" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "İsim:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"URL ve İsim ekleyerek yeni bir arama motoru ekleyebilirsiniz. İsim için, " -"kullanmak istediğiniz arama motorunun adını yazınız. URL için, arama " -"sayfasının adresini yazınız. Kullanıcının arama sorgusu adresteki ${query} " -"değerinin yerini alacaktır.\n" -"Örnek olarak, Google şöyle eklenebilir:\n" -"İsim: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Yardım" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Arama dizgisi" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Motor Seçin" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "Motorları Yönet" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Ara " diff --git a/po/uk.po b/po/uk.po deleted file mode 100644 index acd6b4b7f..000000000 --- a/po/uk.po +++ /dev/null @@ -1,2492 +0,0 @@ -# Ukrainian translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-18 09:30+0000\n" -"Last-Translator: mikhalek \n" -"Language-Team: Ukrainian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:01+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Додати торент" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Додати" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Вилучити торент" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Вилучити" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Вилучити торенти, що роздаються" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Очистити" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Почати або продовжити торент" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Продовжити" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Призупинити торент" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Призупинити" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "Перемістити по черзі вгору" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Вгору" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "Перемістити по черзі вниз" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Вниз" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Змінити налаштування Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Настройки" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Плагіни" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Файл" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Додати торент" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Додати _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Очистити Завершені" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Редагувати" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "Пла_гіни" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Торент" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Вигляд" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "_Панель інструментів" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Детальніше" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Стовпчики" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Розмір" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Статус" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "Поширювачі" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "Вузли" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Швидкість завантаження" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Швидкість розповсюдження" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Залишилось часу" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Наявність" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -#, fuzzy -msgid "Share Ratio" -msgstr "Коефіцієнт обміну" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Допомога" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "Пожертви для проекту Deluge" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_Пожертвувати" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "Домашня сторінка" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "Суспільство" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Допоможіть перекласти цю Програму" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Перекладіть Цю Програму..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "Запуск Помічника Початкових Налаштувань" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "_Запуск Помічника Налаштувань" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Зкачано:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Віддано:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "Роздаючі:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Рейтинг Звант./Вивант.:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Швидкість:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "Викачуючі:" - -#: glade/delugegtk.glade:925 -#, fuzzy -msgid "ETA:" -msgstr "ETA:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Кавалки:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "Доступність:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Статистика" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "к-ть файлів:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Загальний Розмір:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Трекер:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Статус Трекера:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Наступний анонс:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Назва:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Шлях:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Торрент Інфо" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Детальніше" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Ви впевнені, що хочете видалити обраний торрент(и) з " -"Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Видалити звантажені файли" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Видалити .torrent файл" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Показати/Сховати" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Додати Торрент..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Очистку завершено" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Відкрити Файл" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Вибрати Все" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Зняти Виділення" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Не Викачувати" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Звичайна" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Високий" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Найвищий" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge Обєднання списків трекерів" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Торрент вже присутній в Deluge, хочете добавити нові трекери в нього?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Налаштування Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Питати Куди Зерігати кожне Звантаження" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Оберіть папку" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Зберегти всі файли потоків в:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Зберігати Всі Звантаження в:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Держава, з якої йде завантаження" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Автоматично завантажити всі файли потоків в:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Автоматичне завантаження" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -#, fuzzy -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Кількість активних потоків, які буде виконувати Deluge. Встановіть -1 для " -"необмеженої." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Максимальна кількість одночасних активних потоків:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -#, fuzzy -msgid "Enable selecting files for torrents before loading" -msgstr "Дозволити вибірку файлів у потоці перед завантаженням" - -#: glade/preferences_dialog.glade:303 -#, fuzzy -msgid "Only show if torrent has more than 1 file" -msgstr "Показувати, якщо потік містить більше, ніж 1 файл" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -#, fuzzy -msgid "Prioritize first and last pieces of files in torrent" -msgstr "Віддавати перевагу першим і останнім частинам файлів у потоці" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Не починати завантаження відкритих торрентів автоматично" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Потоки" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Повне виділення місця означає, що на жорсткому диску одразу буде створено " -"файли повного розміру. Це також допомагає уникнути фрагментації файлів." - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Використовувати повне виділення місця" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Поступове виділення місця при завантаженні файлів." - -#: glade/preferences_dialog.glade:414 -#, fuzzy -msgid "Use Compact Allocation" -msgstr "Застосувати щільне розміщення" - -#: glade/preferences_dialog.glade:434 -#, fuzzy -msgid "Allocation" -msgstr "Розміщення" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Завантаження" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Зверніть увагу - зміни цих налаштувань будуть застосовані після " -"перезапуску Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Від:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Кому:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge автоматично вибирає кожного разу різні порти для роботи." - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Випадкові порти" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Перевірити активний порт" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Активний порт:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "" -"Розповсюджена хеш-таблиця може покращити кількість активних з'єднань." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -#, fuzzy -msgid "Universal Plug and Play" -msgstr "Універсальний Plug and Play" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "Обмін вузлів" - -#: glade/preferences_dialog.glade:799 -#, fuzzy -msgid "Local Peer Discovery" -msgstr "Знаходження локальних вузлів" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -#, fuzzy -msgid "Inbound:" -msgstr "Вхідні:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -#, fuzzy -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Вимкнений\n" -"Увімкнутий\n" -"Примусовий" - -#: glade/preferences_dialog.glade:877 -#, fuzzy -msgid "Outbound:" -msgstr "Вихідні:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "Шифрувати цілий потік" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Рівень:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Кодування" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Мережа" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Переміщати торренти донизу під час роздачі" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Розміщувати нові потоки над завершеними" - -#: glade/preferences_dialog.glade:1053 -#, fuzzy -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Перестати роздавати торренти коли коефіцієнт роздачі досягне:" - -#: glade/preferences_dialog.glade:1089 -#, fuzzy -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "" -"Автоматично витирати торренти, які мають максимальний коефіцієнт роздачі" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "Зупинити роздачу торрентів якщо час роздачі досягнув:" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "Кількість годин" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "Автоочищення торрентів що досягнули максимуу роздачі" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Роздача" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Поширення" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" -"Максимальна кількість спроб з'єднання за секунду. Деякі дешеві " -"маршрутизатори можуть не справитись з високим значенням. Установіть -1 для " -"необмеженої." - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "Максимальна кількість спроб з'єднання за секунду:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Максимальна швидкість відвантаження для всіх торрентів. Встановити -1 для " -"безлімітного." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Максимальна швидкість роздачі для всіх торрентів. Поставте -1 для " -"необмеженої швидкості." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Максимальна швидкість завантаження для всіх потоків. Установіть -1 для " -"необмеженої." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Максимальна швидкість завантаження (КіБ/с):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "" -"Максимальнo дозволена кількість з'єднань. Установіть -1 для необмеженої." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Максимальна кількість з'єднань:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Максимальна швидкість роздачі (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "Максимальна кількість наполовину відкритих з'єднань:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "Глобальне Використання Трафіку" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" -"Максимальна кількість з'єднань одного потоку. Установіть -1 для необмеженої." - -#: glade/preferences_dialog.glade:1547 -#, fuzzy -msgid "Per Torrent Bandwidth Usage" -msgstr "Завнтаженість смуги пропускання для одного потоку" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "Смуга пропускання" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "Порт" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "Сервер" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"Жодне\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "Пароль:" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "Ім'я користувача" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -#, fuzzy -msgid "Proxy type" -msgstr "Тип Proxy" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "Проксі для трекера" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "Проксі для трекера" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "Проксі для веб-роздачі" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "Проксі для веб-роздачі" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Проксі" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "Ввімкнути піктограму у системному лотку" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "Згорнути в трей при закритті" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "Стартувати в системному лотку" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "Захистити паролем системний лоток" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "Пароль:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "Системний Лоток" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" -"Deluge перевірятиме наші сервери і повідомлятиме про випуск новішої версії" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "Будь в курсі про нові випуски" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "Оновлення" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "Системна інформація" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "Інше" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "_Форсувати Перевірку" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "_Поновити" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "_Призупинити" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Видалити потік" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "О_пції Трекера" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Оновити Трекер" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Редактувати Трекер" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Додати до списку" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "В самий _верх" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "В_гору" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "В_низ" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "З_низу" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Відкриту теку, яка це містить" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "По_казати Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Поновити всі" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "При_зупинити Все" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "Швидкість _закачки" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Швидкість _роздачі" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "Ви_хід" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Редагувати трекери" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "Редагування трекера" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Вибір файлів Deluge" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "Торрент бде розповсюджений сітці (DHT) без відслідковування" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "Установити особисту мітку" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "Налаштування при першому запуску" - -#: glade/wizard.glade:20 -#, fuzzy -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"Цей помічник допоможе зробити Deluge максимально зручною для Вас. Якщо Ви ще " -"не знайомі з Deluge, візьміть до уваги, що функціональність програми і її " -"властивості представлені у формі плагінів, доступ до яких можна отримати " -"натиснувши Плагіни в меню Редагування або на панелі інструментів." - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "Використовувати _Випадкові Порти" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" -"Ви бажаєте щоб Deluge автоматично завантажував до предумовленого місця чи " -"кожен раз окремо будете вказувати місце для завантаження?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "Питати де записувати кожен файл" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "Зберігати все завантаження у: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" -"Оберіть швидкість відвантаження якие потім буде автоматично використано для " -"налаштувань нижче" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "Максимальна кількість активних потоків:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8к\n" -"56к\n" -"64к\n" -"96к\n" -"128к\n" -"192к\n" -"256к\n" -"384к\n" -"512к\n" -"640к\n" -"768к\n" -"1Мбіт\n" -"2Мбіт\n" -"10Мбіт\n" -"20Мбіт\n" -"40Мбіт\n" -"50Мбіт\n" -"100Мбіт" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "КіБ/с" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "Необмежено" - -#: src/interface.py:325 -msgid "Activated" -msgstr "Активовано" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "Інший..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "Швидкість Закачки (KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "Швидкість Роздачі (KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge заблокована" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge захищена паролем.\n" -"Щоб показати вікно Deluge, будь ласка, введіть Ваш пароль" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "Нескінченість" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "Невідомо" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "Ім’я" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "ETA" - -#: src/interface.py:651 -msgid "Avail." -msgstr "Дост." - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "Відношення" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "Призупинений %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "У черзі %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "Є новіша версія Deluge. Ви б хотіли перейти до нашого сайту?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "З'єднання" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "Завантажити" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "Відправити" - -#: src/interface.py:1268 -#, fuzzy -msgid "Deluge Bittorrent Client" -msgstr "Клієнт Bittorrent Deluge" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "Виберіть адресу для завантаження" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "Не вистачає вільної пам'яті на диску, щоб завершити завантаження." - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "Потрібно пам'яті :" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "Доступно пам'яті:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "Додати потік з URL" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "Введіть URL файлу .torrent для завантаження" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "Обережно - всі завантажені файли цього потоку будуть видалені!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "Ви впевнені що бажаєте видалити всі торренти на роздачі?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "В черзі" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "Перевірка" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "З'єднання" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "Завантаження мета-даних" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "Завантаження" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "Завершено" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "байт потрібно" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "Не вистачає вільного дискового простору для завершення завантаження." - -#: src/core.py:761 -#, fuzzy -msgid "Announce sent" -msgstr "Запит вислано" - -#: src/core.py:765 -#, fuzzy -msgid "Announce OK" -msgstr "Запит ОК" - -#: src/core.py:774 -msgid "Alert" -msgstr "Попередження" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP код" - -#: src/core.py:776 -msgid "times in a row" -msgstr "разів підряд" - -#: src/core.py:788 -msgid "Warning" -msgstr "Попередження" - -#: src/files.py:77 -msgid "Filename" -msgstr "Ім'я файлу" - -#: src/files.py:82 -msgid "Priority" -msgstr "Пріоритет" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "Плагін" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "Увімкнено" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "Виберіть файл .torrent" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "Файли потоків" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "Всі файли" - -#: src/common.py:88 -msgid "KiB" -msgstr "КіБ" - -#: src/common.py:91 -msgid "MiB" -msgstr "МіБ" - -#: src/common.py:94 -msgid "GiB" -msgstr "ГіБ" - -#: src/common.py:97 -msgid "TiB" -msgstr "ТіБ" - -#: src/common.py:99 -msgid "PiB" -msgstr "ПіБ" - -#: src/common.py:206 -msgid "External command" -msgstr "Зовнішня команда" - -#: src/common.py:207 -msgid "not found" -msgstr "не знайдено" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian Текст (Некомпресований)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP список (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer текст (zip-архів)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "Неможливо завантажити URL" - -#: plugins/BlocklistImport/__init__.py:131 -#, fuzzy -msgid "Couldn't open blocklist file" -msgstr "Неможливо відкрити blocklist-файл" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -#, fuzzy -msgid "Wrong file type or corrupted blocklist file." -msgstr "Неправильний тип файлу або пошкоджений blocklist-файл" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "Імпортовано" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "Адреси IP" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "Blocklist" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "компоненти" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "Blocklist URL" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -#, fuzzy -msgid "Loading and installing blocklist" -msgstr "Видобування і інсталяція blocklist" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "Імпорт" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "Закінчити" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "Неправильна версія" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "Установіть бажане відношення для потоку." - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "_Бажаний рівень" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "Не встановлено" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "Бажане відношення" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"Покаже Вам вузли, підключені до кожного потоку, їх IP, країну, клієнт, " -"скільки процентів завантажено та вхідну і вихідну швидкість.\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "Адреса IP" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "Клієнт" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "Відсотків виконано" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "Створювач потоків" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "Цей потік буде створено з одного файлу" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "Файл:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "Цей потік буде створено з теки" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "Тека:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "Джерело" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "Зберегти файл потоку як:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "Завантажити цей торрент у Deluge для роздачі" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "Додати новий потік в чергу" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "Файл потоку" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "Коментарі" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "Автор" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "Встановити особисту мітку" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" -"Чим менший розмір частинок, тим ефективніша передача, але поточний файл " -"\".torrent\" більший" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 КіБ\n" -"64 КіБ\n" -"128 КіБ\n" -"256 КіБ\n" -"512 КіБ\n" -"1024 КіБ\n" -"2048 КіБ\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "Розмір частинки:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "Розширені" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "Плагін створення потоків" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "_Новий Торрент" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "Новий потік" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "Створити новий потік" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "Зберегти файл як..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "Потрібно вказати джерело потоку." - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "Потрібно вказати файл, щоб зберегти потік як." - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "Дозволити мигаючу іконку в системному лотку" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -#, fuzzy -msgid "Torrent complete" -msgstr "Торрент закінчений" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[Здоров'я: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "Дозволити файли з логами" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "Лог-файли" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "Блокувати завершені" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "Блокувати завантаження" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "Шматок завершено" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Попередження трекеру" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Відповідь трекеру" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "Помилка файлу" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "Недійсний запит" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "Торрент завершено" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip адреса: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "клієнт: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "частина індексу: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "Блокувати індекс: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "Встановіть бажаний ліміт швидкості для кожного торренту." - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "Torrent _Швидкість завантаження" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "Torrent _Швидкість відвантаження" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "Швидість відвантаження торрентів (KiB/с):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "Швидкість завантаження торрентів (KiB/с):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "_Перемістити торрент" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "Обмеження завантаження:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "Обмеження відвантаження:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "Активні торренти:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "Новий пароль" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "Новий пароль(підтвердити)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "Стиль кнопок" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "Текст та зображення" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "Тільки зображення" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "Тільки текст" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "перекладіть щось" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "немає даних" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# файлів" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "Додати торрент" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "Видалити завантажені файли." - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "Неправильний пароль, спробуйте знову" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "Пауза всі" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "Шматки" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "Відновити всі" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "Список торрентів" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Трекер" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Статус трекеру" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "Відвантажити торрент" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "Відвантажено" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "Через" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "Не пасує" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "Tест" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "Вставте торрент на початок списку" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "Звантажити" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "Оберіть" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "Інтерфейс" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "Домен" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Шлях" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "Значення" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Коржики" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "Налаштування" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Налаштувати розширення для пошуку" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Ім'я:" - -#: plugins/Search/searchdlg.glade:123 -#, fuzzy -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Ви можете додати нову пошукову систему, ввівши її Ім'я або URL. Якщо це Ім'я " -"- введіть назву пошукової системи. Якщо URL - введіть url до пошукової " -"сторінки. Запит користувача замінить ${query} в полі URL.\n" -"Наприклад, Google пошук:\n" -"Ім'я: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Довідка" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "Пошук торрентів приватно" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "Стрічка пошуку" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "Оберіть двигун" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "Пошук " diff --git a/po/vi.po b/po/vi.po deleted file mode 100644 index b1dabb659..000000000 --- a/po/vi.po +++ /dev/null @@ -1,2417 +0,0 @@ -# Vietnamese translation for deluge -# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2007. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: Lê Bình \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-18 14:31+0000\n" -"Last-Translator: Long Tran \n" -"Language-Team: Vietnamese \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "Thêm Torrent" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "Thêm" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "Loại bỏ Torrent" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "Loại bỏ" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "Xóa các torrent đang seed" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "Xóa" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "Bắt đầu hay tiếp tục Torrent" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "Tiếp tục" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "Tạm dừng Torrent" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "Tạm dừng" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "Lên" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "Xuống" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "Thay đổi tuỳ thích của Deluge" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "Tuỳ thích" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "Phần bổ sung" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_Tập tin" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "_Thêm torrent" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "Thêm _URL" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "_Xoá torrent đã hoàn tất" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_Hiệu chỉnh" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "_Phần bổ sung" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "_Torrent" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "_Xem" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "Thanh _Công cụ" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "_Chi tiết" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "_Cột" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "Kích cỡ" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "Trạng thái" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "Tốc độ tải xuống" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "Tốc độ tải lên" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "Thời gian còn lại" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "Khả dụng" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "Tỷ lệ chia sẻ" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_Trợ giúp" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "_Trang chủ" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "_FAQ" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "_Cộng đồng" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "Hỗ trợ chuyển ngữ chương trình này" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "_Chuyển ngữ chương trình này" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "Đã tải xuống:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "Đã tải lên:" - -#: glade/delugegtk.glade:827 -#, fuzzy -msgid "Seeders:" -msgstr "Người cung cấp:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "Tỷ lệ chia sẻ:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "Tốc độ:" - -#: glade/delugegtk.glade:904 -#, fuzzy -msgid "Peers:" -msgstr "Đối tác:" - -#: glade/delugegtk.glade:925 -#, fuzzy -msgid "ETA:" -msgstr "Ước lượng:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "Số phân mảnh:" - -#: glade/delugegtk.glade:980 -#, fuzzy -msgid "Availability:" -msgstr "Mức khả dụng:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "Thống kê" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "Số tập tin:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "Kích thước tổng:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Người theo dõi:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Trạng thái người theo dõi:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "Thông báo kế:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "Tên:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "Đường dẫn:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "Thông tin torrent" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "Chi tiết" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "" -"Bạn có chắc chắn là muốn loại bỏ những torrentđã lựa " -"chọn khỏi Deluge?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "Xoá tập tin đã tải xuống" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "Xoá tập tin .torrent" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "Hiện/Ẩn" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "Thêm một Torrent..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "Xoá những torrent đã hoàn tất" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "_Mở tập tin" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "Chọn tất cả" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "Bỏ chọn tất cả" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "Đừng tải xuống" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "Thường" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "Cao" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "Cao nhất" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Trộn danh sách tracker - Deluge" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "" -"Phát hiện torrent đã có trong Deluge, bạn có muốn trộn danh sách trackerlại?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Tuỳ thích Deluge" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "Hỏi địa điểm để lưu mỗi khi tải xuống" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "Lựa chọn một thư mục" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "Lưu toàn bộ tập tin torrent trong:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "Lưu toàn bộ tải xuống trong:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "Địa điểm tải xuống" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "Tự động nạp tất cả tập tin torrent trong:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "Tự động nạp" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "" -"Số lượng torrent tích cực mà Deluge sẽ chạy. Thiết lập bằng -1 để không giới " -"hạn." - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "Số lượng tối đa torren tích cực cùng lúc:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "Cho phép lựa chọn tập tin cho torrent trước khi tải" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "Chỉ hiện nếu torrent có nhiều hơn 1 tập tin" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "Bắt đầu torrent trong trạng thái tạm dừng" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "Torrents" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "" -"Cấp pháp toàn bộ sẽ cấp phát trước toàn bộ dung lượng đĩa cần thiết cho " -"torrentvà ngăn ngừa được sự phân mảnh tập tin" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "Sử dụng cấp phát toàn bộ" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "Cấp phát rút gọn chỉ cấp phát đúng dung lượng cần thiết tạm thời" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "Sử dụng cấp phát rút gọn" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "Cấp phát" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "Tải xuống" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "" -"Vui lòng chú ý - Thay đổi những thiết lập này chỉ có hiệu lực sau khi " -"đãkhởi động lại Deluge." - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "Từ:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "Tới:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge sẽ tự động chọn 1 cổng khác để sử dụng" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "Cổng ngẫu nhiên" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "Thử cổng tích cực" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "Cổng tích cực:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "Bảng băm phân tán (DHT) có thể cải thiện số lượng kết nối tích cực." - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "Bật chế độ DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "Dữ liệu nhận" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"Tắt\n" -"Bật\n" -"Bắt buộc" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "Dữ liệu truyền đi" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "Cấp:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "Mã hóa" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "Mạng" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "Xếp torrent xuống dưới khi chúng bắt đầu seed" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "Xếp torrent lên trên các torrent đã tải xong" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "Dừng seed khi các torrent có ratio lớn hơn:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "Tự động xóa các torrent đạt đến ratio lớn nhất" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "Đang tải lên" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "Tải lên" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "" -"Số đường tải lên nhiều nhất, áp dụng cho tất cả torrent. Đặt giá trị -1 là " -"không giới hạn." - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "" -"Tốc độ tải lên tối đa, áp dụng cho tất cả torrent. Đặt giá trị -1 là không " -"giới hạn." - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "" -"Tốc độ tải xuống lớn nhất, áp dụng cho tất cả torrent. Đặt giá trị -1 là " -"không giới hạn." - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "Tốc độ tải xuống lớn nhất (KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "Số kết nối cho phép nhiều nhất. Đặt giá trị -1 là không giới hạn." - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "Kết nối nhiều nhất:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "Tốc độ tải lên lớn nhất (KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "Số đường tải lên lớn nhất:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "Tiếp tụ_c" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "Tạm _dừng" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "_Loại bỏ Torrent" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "_Thiết lập tracker" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_Cập nhật Tracker" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "_Biên tập các Tracker" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "_Hàng đợi" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "_Trên cùng" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "_Lên" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "_Xuống" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "_Dưới cùng" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "_Mở thư mục chứa" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "_Hiện Deluge" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "_Tiếp tục tất cả" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "Tạm _dừng tất cả" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "_Giới hạn tốc độ tải xuống" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "Giới _hạn tốc độ tải lên" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "_Thoát" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "Biên tập các Tracker" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "" - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "" - -#: src/interface.py:325 -msgid "Activated" -msgstr "" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "" - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "" - -#: src/interface.py:651 -msgid "Avail." -msgstr "" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "" - -#: src/core.py:774 -msgid "Alert" -msgstr "" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "" - -#: src/core.py:776 -msgid "times in a row" -msgstr "" - -#: src/core.py:788 -msgid "Warning" -msgstr "" - -#: src/files.py:77 -msgid "Filename" -msgstr "" - -#: src/files.py:82 -msgid "Priority" -msgstr "" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "" - -#: src/common.py:88 -msgid "KiB" -msgstr "" - -#: src/common.py:91 -msgid "MiB" -msgstr "" - -#: src/common.py:94 -msgid "GiB" -msgstr "" - -#: src/common.py:97 -msgid "TiB" -msgstr "" - -#: src/common.py:99 -msgid "PiB" -msgstr "" - -#: src/common.py:206 -msgid "External command" -msgstr "" - -#: src/common.py:207 -msgid "not found" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "" - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "URL:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "Đa luồng (thử nghiệm)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "Đường dẫn" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "Quản lý công cụ tìm kiếm bổ sung" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "Tên:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"Thêm một máy tìm kiếm mới bằng cách nhập vào Tên và URL của nó.Với phần Tên, " -"nhập vào tên mà bạn muốn sử dụng cho máy tìm kiếm.Với phần URL, nhập vào URL " -"của trang tìm kiếm; truy vấn của bạn sẽ được thay thế bất cứ chuỗi ${query} " -"nào trong URL.\n" -"Ví dụ, để tìm kiếm sử dụng Google:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "Trợ giúp" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "" diff --git a/po/zh_CN.po b/po/zh_CN.po deleted file mode 100644 index 535aabd56..000000000 --- a/po/zh_CN.po +++ /dev/null @@ -1,3080 +0,0 @@ -# Chinese (China) translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: deluge\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-04-28 22:13+0000\n" -"Last-Translator: zhuqin \n" -"Language-Team: Chinese (China) \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" - -#~ msgid "Clear Finished Torrents" -#~ msgstr "清除已完成种子" - -#~ msgid "Total Downloaded" -#~ msgstr "总共已下载" - -#~ msgid "Total Uploaded" -#~ msgstr "总共已上传" - -#~ msgid "translator-credits" -#~ msgstr "" -#~ "Launchpad Contributions:\n" -#~ " Abcx \n" -#~ " Jack Shen \n" -#~ " XavierToo \n" -#~ " Xiaodong Xu \n" -#~ " butely \n" -#~ " darh00 \n" -#~ " duan \n" -#~ " oldbeggar \n" -#~ " qubicllj \n" -#~ " rainofchaos \n" -#~ " smoke \n" -#~ " xyb \n" -#~ " zissan \n" -#~ "\n" -#~ "Launchpad Contributions:\n" -#~ " Aaron Wang Shi \n" -#~ " Abcx \n" -#~ " Jack Shen \n" -#~ " Wentao Tang \n" -#~ " XavierToo \n" -#~ " Xiaodong Xu \n" -#~ " butely \n" -#~ " darh00 \n" -#~ " duan \n" -#~ " oldbeggar \n" -#~ " qubicllj \n" -#~ " rainofchaos \n" -#~ " smoke \n" -#~ " xyb \n" -#~ " zissan \n" -#~ "\n" -#~ "Launchpad Contributions:\n" -#~ " Aaron Wang Shi \n" -#~ " Abcx \n" -#~ " Jack Shen \n" -#~ " Wentao Tang \n" -#~ " XavierToo \n" -#~ " Xiaodong Xu \n" -#~ " butely \n" -#~ " darh00 \n" -#~ " duan \n" -#~ " laughterwym \n" -#~ " oldbeggar \n" -#~ " qubicllj \n" -#~ " rainofchaos \n" -#~ " smoke \n" -#~ " xyb \n" -#~ " zissan \n" -#~ "\n" -#~ "Launchpad Contributions:\n" -#~ " Aaron Wang Shi https://launchpad.net/~aarons-wang\n" -#~ " Abcx https://launchpad.net/~xinwen87-gmail\n" -#~ " Jack Shen https://launchpad.net/~anticlockwise5\n" -#~ " Wentao Tang https://launchpad.net/~wisetang\n" -#~ " XavierToo https://launchpad.net/~xaviertoo\n" -#~ " Xiaodong Xu https://launchpad.net/~xxdlhy\n" -#~ " Zissan https://launchpad.net/~zissan\n" -#~ " butely https://launchpad.net/~moosefly\n" -#~ " darh00 https://launchpad.net/~darren-hoo\n" -#~ " duan https://launchpad.net/~duanzhiwei\n" -#~ " ibear https://launchpad.net/~bearsprite\n" -#~ " laughterwym https://launchpad.net/~edwin.wang\n" -#~ " oldbeggar https://launchpad.net/~chen-gang1983\n" -#~ " qubicllj https://launchpad.net/~qubicllj-gmail\n" -#~ " rainofchaos https://launchpad.net/~rainofchaos\n" -#~ " smoke https://launchpad.net/~minir4id\n" -#~ " xyb https://launchpad.net/~xieyanbo\n" -#~ " zhuqin_83 https://launchpad.net/~zhuqin-83\n" -#~ "\n" -#~ "Launchpad Contributions:\n" -#~ " Aaron Wang Shi https://launchpad.net/~aarons-wang\n" -#~ " Abcx https://launchpad.net/~xinwen87-gmail\n" -#~ " Jack Shen https://launchpad.net/~anticlockwise5\n" -#~ " Larry W. Liu https://launchpad.net/~larryweiliu\n" -#~ " Wentao Tang https://launchpad.net/~wisetang\n" -#~ " XavierToo https://launchpad.net/~xaviertoo\n" -#~ " Xiaodong Xu https://launchpad.net/~xxdlhy\n" -#~ " Zissan https://launchpad.net/~zissan\n" -#~ " butely https://launchpad.net/~moosefly\n" -#~ " darh00 https://launchpad.net/~darren-hoo\n" -#~ " duan https://launchpad.net/~duanzhiwei\n" -#~ " ibear https://launchpad.net/~bearsprite\n" -#~ " laughterwym https://launchpad.net/~edwin.wang\n" -#~ " oldbeggar https://launchpad.net/~chen-gang1983\n" -#~ " qubicllj https://launchpad.net/~qubicllj-gmail\n" -#~ " rainofchaos https://launchpad.net/~rainofchaos\n" -#~ " smoke https://launchpad.net/~minir4id\n" -#~ " xyb https://launchpad.net/~xieyanbo\n" -#~ " zhuqin https://launchpad.net/~zhuqin" - -#~ msgid "Plugin Manager" -#~ msgstr "插件管理器" - -#~ msgid "Columns" -#~ msgstr "列" - -#~ msgid "Options" -#~ msgstr "选项" - -#~ msgid "Use compact storage allocation" -#~ msgstr "使用紧凑的存储分配" - -#~ msgid "File was not found" -#~ msgstr "找不到文件" - -#~ msgid "" -#~ "Compact allocation will only allocate as much storage as it needs to keep " -#~ "the pieces downloaded so far." -#~ msgstr "使用紧凑分配下载,仅申请用于保存当前下载区块的空间。" - -#, fuzzy -#~ msgid "Compact Allocation" -#~ msgstr "紧凑磁盘分配设置" - -#~ msgid "Bandwidth Usage" -#~ msgstr "所占用带宽" - -#~ msgid "TCP Port" -#~ msgstr "TCP端口" - -#~ msgid "" -#~ "Handshake\n" -#~ "Either\n" -#~ "Full Stream" -#~ msgstr "" -#~ "握手(低)\n" -#~ "两者之一(中)\n" -#~ "全部数据流(高)" - -#~ msgid "GUI update interval (seconds)" -#~ msgstr "界面更新间隔(秒)" - -#~ msgid "Performance" -#~ msgstr "性能" - -#~ msgid "Start or Pause torrent" -#~ msgstr "开始或停止种子" - -#~ msgid "Open the plugins dialog" -#~ msgstr "打开插件窗口" - -#~ msgid "Pl_ugins" -#~ msgstr "插件(_U)" - -#~ msgid "Speed:" -#~ msgstr "速度:" - -#~ msgid "Move completed downloads to (*same partition only*):" -#~ msgstr "完成下载后把文件移动到(仅限相同分区):" - -#~ msgid "µTorrent Peer-Exchange" -#~ msgstr "与µTorrent交换对等伙伴" - -#~ msgid "µTorrent-PeX" -#~ msgstr "µTorrent-Pex" - -#~ msgid "" -#~ "Only affects HTTP tracker connections (UDP tracker connections are affected " -#~ "if the given proxy supports UDP, e.g. SOCKS5)." -#~ msgstr "只允许使用HTTP tracker连接(加入你的代理支持UDP(例如SOCK5),UDP tracker连接将会应用生效)" - -#~ msgid "" -#~ "Affects the DHT messages. Since they are sent over UDP, it only has any " -#~ "effect if the proxy supports UDP." -#~ msgstr "这会影响到DHT信息传播。代理服务器支持UDP传输,才会生效。" - -#~ msgid "Proxy" -#~ msgstr "代理" - -#~ msgid "_Clear Finished" -#~ msgstr "_清除完成" - -#~ msgid "_Down Speed Limit" -#~ msgstr "_下载速度限制" - -#~ msgid "_Up Speed Limit" -#~ msgstr "_上存速度限制" - -#~ msgid "Pause/Resume" -#~ msgstr "暂停/恢复" - -#~ msgid "" -#~ "You cannot move torrent to a different partition. Please fix your " -#~ "preferences" -#~ msgstr "您不能移动种子到另外一个分区。请修改设置" - -#~ msgid "Asked for a torrent that doesn't exist" -#~ msgstr "找不到你所选择的种子" - -#~ msgid "Torrent Search" -#~ msgstr "搜索种子" - -#~ msgid "You must specify at least one tracker." -#~ msgstr "你必须至少指定一个服务器器" - -#~ msgid "" -#~ "32 KiB\n" -#~ "64 KiB\n" -#~ "128 KiB\n" -#~ "256 KiB\n" -#~ "512 KiB\n" -#~ "1024 KiB\n" -#~ msgstr "" -#~ "32KiB\n" -#~ "64KiB\n" -#~ "128KiB\n" -#~ "256KiB\n" -#~ "512KiB\n" -#~ "1024KiB\n" - -#~ msgid "Network Activity Graph" -#~ msgstr "网络统计图" - -#~ msgid "Network Health Monitor" -#~ msgstr "网络状态监视器" - -#~ msgid "RSS Broadcatcher" -#~ msgstr "RSS猎手" - -#~ msgid "" -#~ "\n" -#~ "Download Torrents automatically from RSS Feeds\n" -#~ "\n" -#~ "The latest version of my RSS autodownloader, which uses the Universal Feed " -#~ "parser (http://feedparser.org/). Add RSS feeds on the 'Feeds' tab, then add " -#~ "filters for TV shows (or whatever) on the 'Filters' tab. Double-click " -#~ "entries on the 'Torrents' tab to download extra torrents from the feeds. The " -#~ "Options are pretty self-explanatary.\n" -#~ "\n" -#~ "Please message me (SatNav) on the forums and let me know how you get on..\n" -#~ "\n" -#~ "Enjoy!" -#~ msgstr "" -#~ "\n" -#~ "自动从RSS下载种子" - -#~ msgid "Last Entry Date" -#~ msgstr "最后记录日期" - -#~ msgid "Date" -#~ msgstr "日期" - -#~ msgid "RSS" -#~ msgstr "RSS" - -#~ msgid "New Filter" -#~ msgstr "新建过滤规则" - -#~ msgid "All" -#~ msgstr "所有" - -#~ msgid "RSS Broadcatcher Settings" -#~ msgstr "RSS猎手设置" - -#~ msgid "Feed Name:" -#~ msgstr "来源名称" - -#~ msgid "Feed URL:" -#~ msgstr "来源 URL" - -#~ msgid "Filter Exp:" -#~ msgstr "过滤表达式:" - -#~ msgid "Filter Name:" -#~ msgstr "过滤器名称:" - -#~ msgid " Feed: " -#~ msgstr " 来源: " - -#~ msgid "Torrents" -#~ msgstr "种子" - -#~ msgid "Update Interval (seconds): " -#~ msgstr "更新时间间隔 " - -#~ msgid "Check feeds on Deluge start" -#~ msgstr "在Deluge启动时检查来源" - -#~ msgid "Check Feeds Now" -#~ msgstr "马上检查来源" - -#~ msgid "Blocklist Importer" -#~ msgstr "黑名单加载器" - -#~ msgid "Format error in blocklist" -#~ msgstr "过滤列表格式错误" - -#~ msgid "Download on start" -#~ msgstr "当程序启动时开始下载" - -#~ msgid "Couldn't match on line" -#~ msgstr "在该行中,找不到匹配的" - -#~ msgid "" -#~ "File priority can only be set when using full allocation.\n" -#~ "Please change your preference to disable compact allocation, then remove and " -#~ "readd this torrent." -#~ msgstr "" -#~ "文件优先级只能在使用预先分配磁盘空间的情况下使用。\n" -#~ "请在选项中停用紧凑分配,删除并重新加入这个种子。" - -#~ msgid "Maximum Global Upload Slots:" -#~ msgstr "全局最大上传通道:" - -#~ msgid "Global _Down Speed Limit" -#~ msgstr "全局下载速度限制(_D)" - -#~ msgid "Global _Up Speed Limit" -#~ msgstr "全局上传速度限制(_U)" - -#~ msgid "Torrent Pieces" -#~ msgstr "种子分块" - -#~ msgid "Torrent Peers" -#~ msgstr "种子的用户" - -#~ msgid "" -#~ "\n" -#~ "This is just the peers tab as a plugin.\n" -#~ msgstr "" -#~ "\n" -#~ "本插件可以显示一个连接标签.\n" - -#~ msgid "Enable event sound (requires pygame)" -#~ msgstr "开启声音提示(需要pygame)" - -#~ msgid "Enable popup notification (requires python-notify)" -#~ msgstr "弹出提示(需要python-notify)" - -#~ msgid "Torrent Notification" -#~ msgstr "种子提示" - -#~ msgid "Event Logging" -#~ msgstr "事件日志" - -#~ msgid "Speed Limiter" -#~ msgstr "速度限制" - -#~ msgid "Piece shared with next file(s)" -#~ msgstr "与下一个文件共享的分块" - -#~ msgid "Locations" -#~ msgstr "位置" - -#~ msgid "" -#~ "Automagically remembers relevant settings for different locations.\n" -#~ "\n" -#~ "When this plugin is active, it will remember a lot of useful network-" -#~ "specific preferences, such as up- or download limits, open ports and proxy " -#~ "information. Just change preferences to suit each location while connected, " -#~ "and Deluge will automagically use those settings the next time you connect " -#~ "at that location. There is no other configuration needed.\n" -#~ "\n" -#~ "The plugin determines location by identifying the unique MAC address of the " -#~ "Gateway used for the connection. It is therefore possible to have different " -#~ "settings for home and work, or for broadband, 3G and dial-up on the fly.\n" -#~ msgstr "" -#~ "自动记住对不同位置的相关设定。\n" -#~ "\n" -#~ "当插件被激活,它会记住大量有用的网络特定选项,例如上传下载限制、开发的端口、代理信息等。每次连接时,只需选择适合该位置的选项,Deluge就会在你再次连到" -#~ "该地时,自动使用哪些设定。不需要任何其他配置。\n" -#~ "\n" -#~ "插件通过识别连接网关的唯一MAC地址来确定位置。对家庭和工作的不同情况,或者对广播、3G和拨号等不同连接形式都可以有不同的设置。\n" - -#~ msgid "Torrent Files" -#~ msgstr "种子文件" - -#~ msgid "" -#~ "\n" -#~ "This is just the files tab as a plugin.\n" -#~ msgstr "" -#~ "\n" -#~ "这是文件标签插件\n" - -#~ msgid "" -#~ "Konqueror\n" -#~ "Nautilus\n" -#~ "Thunar" -#~ msgstr "" -#~ "Konqueror\n" -#~ "Nautilus\n" -#~ "Thunar" - -#~ msgid "Custom:" -#~ msgstr "自定义:" - -#~ msgid "Open folder with:" -#~ msgstr "目录浏览程序:" - -#~ msgid "Desktop File Manager" -#~ msgstr "桌面文件管理器" - -#~ msgid "Simple RSS" -#~ msgstr "Simple RSS" - -#~ msgid "" -#~ "\n" -#~ "Download Torrents automatically from SimpleRSS Feeds\n" -#~ "\n" -#~ "Add RSS feeds on the 'Feeds' tab, then add filters for TV shows (or " -#~ "whatever) on the 'Filters' tab. Double-click entries on the 'Torrents' tab " -#~ "to download extra torrents from the feeds. The Options are pretty self-" -#~ "explanatary.\n" -#~ "\n" -#~ "Please message me (SatNav) on the forums and let me know how you get on..\n" -#~ "\n" -#~ "Enjoy!" -#~ msgstr "" -#~ "\n" -#~ "自动从 RSS 订阅中下载种子\n" -#~ "\n" -#~ "在 Feeds 标签添加 RSS 订阅,然后在 Filters 标签添加过滤规则。双击 Torrents 标签开始下载种子。\n" -#~ "\n" -#~ "请你在论坛发信息给我(SatNav),以便让我知道你的进展。" - -#~ msgid "SimpleRSS Broadcatcher" -#~ msgstr "SimpleRSS Broadcatcher" - -#~ msgid "" -#~ "\n" -#~ "Pieces tab now shows percentage instead\n" -#~ "of progress bars. There are no longer any tooltips.\n" -#~ "\n" -#~ "Peer speed uses following symbols:\n" -#~ "fast is +\n" -#~ "medium is =\n" -#~ "slow is -\n" -#~ "\n" -#~ "monospace font is required for columns to be aligned.\n" -#~ "\n" -#~ "Font size and number of columns are configurable in the\n" -#~ "preferences.\n" -#~ "\n" -#~ "Finished torrents do not show piece information, just\n" -#~ "a message that the torrent is complete.\n" -#~ msgstr "" -#~ "\n" -#~ "分块标签现在显示进度条百分比。\n" -#~ "不再有任何工具提示了。\n" -#~ "\n" -#~ "对等连接速度用下面的符号表示:\n" -#~ "“快”是“+“\n" -#~ "“中等”是“=“\n" -#~ "“慢”是“-“\n" -#~ "列对其需要等宽字体。\n" -#~ "\n" -#~ "列的字体和字号可以在首选项里设定。\n" -#~ "\n" -#~ "已完成的种子不显示分块信息,只显示种子已完成。\n" - -#~ msgid "Alltime Stats" -#~ msgstr "Alltime Stats" - -#~ msgid "" -#~ "\n" -#~ "Shows alltime stats in the tray tooltip.\n" -#~ "Tracks transfer amounts, ratio, number of torrents finished, and uptime.\n" -#~ "Also show session uptime\n" -#~ msgstr "" -#~ "\n" -#~ "在托盘工具提示里显示全程状态。\n" -#~ "Tracks服务器流量,分享率,已完成种子数,和运行时间。\n" -#~ "也显示本次回话运行时间\n" - -#~ msgid "Undefined" -#~ msgstr "未定义" - -#~ msgid "Uptime" -#~ msgstr "运行时间" - -#~ msgid "All-time Downloaded" -#~ msgstr "全程已下载" - -#~ msgid "All-time Uploaded" -#~ msgstr "全程已上传" - -#~ msgid "All-time Ratio" -#~ msgstr "全程分享率" - -#~ msgid "Torrents completed" -#~ msgstr "已完成种子" - -#~ msgid "All-time Uptime" -#~ msgstr "全程运行时间" - -#~ msgid "Pieces Preferences" -#~ msgstr "分块选项" - -#~ msgid "Select number of columns" -#~ msgstr "选择列数" - -#~ msgid "Select font size" -#~ msgstr "选择字体大小" - -#~ msgid "Peers Preferences" -#~ msgstr "连接设置" - -#~ msgid "Enable flags" -#~ msgstr "显示国旗" - -#~ msgid "Select size of flag" -#~ msgstr "选择国旗大小" - -#~ msgid "18x12" -#~ msgstr "18x12" - -#~ msgid "25x15" -#~ msgstr "25x15" - -#~ msgid "Extra Stats" -#~ msgstr "扩展统计" - -#~ msgid "Torrents Completed" -#~ msgstr "种子已完成" - -#~ msgid "Running Time" -#~ msgstr "已运行时间" - -#~ msgid "Move Torrent" -#~ msgstr "移动种子" - -#~ msgid "" -#~ "You cannot move torrent to a different partition. Please check your " -#~ "preferences. Or perhalps you are trying to move torrent's files to the same " -#~ "directory they are already stored?" -#~ msgstr "您不能把种子移动到不同的另一个分区中。请检查设置。也许或者是您正在把种子文件移动到保存它们的同一个目录中?" - -#~ msgid "Web Seed" -#~ msgstr "Web种子" - -#~ msgid "Open Containing Folder Preferences" -#~ msgstr "打开下载文件夹参数" - -#~ msgid "" -#~ "28.8k\n" -#~ "56k\n" -#~ "64k\n" -#~ "96k\n" -#~ "128k\n" -#~ "192k\n" -#~ "256k\n" -#~ "384k\n" -#~ "512k\n" -#~ "640k\n" -#~ "768k\n" -#~ "1Mbit\n" -#~ "2Mbit\n" -#~ "10Mbit\n" -#~ "20Mbit\n" -#~ "40Mbit\n" -#~ "50Mbit\n" -#~ "10Mbit" -#~ msgstr "" -#~ "28.8k\n" -#~ "56k\n" -#~ "64k\n" -#~ "96k\n" -#~ "128k\n" -#~ "192k\n" -#~ "256k\n" -#~ "384k\n" -#~ "512k\n" -#~ "640k\n" -#~ "768k\n" -#~ "1Mbit\n" -#~ "2Mbit\n" -#~ "10Mbit\n" -#~ "20Mbit\n" -#~ "40Mbit\n" -#~ "50Mbit\n" -#~ "10Mbit" - -#~ msgid "Queue pos:" -#~ msgstr "队列位置:" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "添加种子" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "添加" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "删除种子" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "删除" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "清除正在作种的种子" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "清除" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "开始或恢复种子" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "续传" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "暂停种子" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "暂停" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "在队列中上移种子" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "上移" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "在队列中下移种子" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "下移" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "更改 Deluge 设置" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "首选项" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "插件" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "文件(_F)" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "添加种子(_A)" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "添加 URL(_U)" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "清除已完成的(_C)" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "编辑(_E)" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "插件(_G)" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "种子(_T)" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "查看(_V)" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "工具栏(_T)" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "详细信息(_D)" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "列(_C)" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "大小" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "状态" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "种子" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "对等连接" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "下载速度" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "上传速度" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "剩余时间" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "健康度" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "分享率" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "帮助(_H)" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "捐赠Deluge开发" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "捐赠(_D)" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "主页(_H)" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "常见问题(_FAQ)" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "社区(_C)" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "帮助翻译此程序" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "翻译此程序(_T)" - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "运行首次配置向导" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "运行配置向导(_R)" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "已下载:" - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "已上传:" - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "种子数:" - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "分享率:" - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "速度:" - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "连接数:" - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "估计剩余时间:" - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "块:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "健康度:" - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "统计" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "包含文件数:" - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "总大小:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "Tracker:" - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "Tracker状态:" - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "下次通报:" - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "名称:" - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "路径:" - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "种子信息" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "详细信息" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "你确认要删除选中的种子吗?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "删除已下载的文件" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "删除种子文件" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "显示/隐藏" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "添加种子..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "清除已完成的种子" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "打开文件(_O)" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "全选" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "取消全选" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "不下载" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "正常" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "高" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "最高" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge合并的Tracker列表" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "该种子已存在于Deluge,你希望合并tracker列表吗?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge首选项" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "每次下载时询问保存目录" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "选择文件夹" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "将所有种子存储在:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "保存所有下载文件到:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "下载位置" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "将所有种子自动载入到:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "自动载入" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "Deluge允许的最大同时活动种子数量。-1为无限制。" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "最大同时活动种子数:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "添加种子时,询问需要下载的文件" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "仅当种子有多于1个文件时显示" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "优先下载文件的首尾部分" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "开始时暂停" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "种子" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "对种子文件所需的磁盘空间进行完全预分配以防止磁盘碎片" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "使用完全分配" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "紧凑分配仅对所需的磁盘空间进行分配" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "使用紧凑分配" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "存储分配" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "下载" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "请注意:所有更改只有重新启动Deluge后才能生效!" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "起始端口:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "结束端口:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge每次会随机选择一个不同的端口。" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "随机端口" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "测试活动端口" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "活动端口:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "分布式哈希表(DHT)技术可以提高可用连接数量。" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "启用主干DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT端口映射协议" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "来源交换" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "发现本地来源" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "附加外部网络" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "本地网络:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"关闭\n" -"启动\n" -"强制" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "外部网络:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "优先加密整个数据流(RC4)" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "加密级别" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"握手(简单加密)\n" -"全数据流(RC4加密)\n" -"两者择一" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "加密传输" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "网络" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "当开始做种时,移动到队列末尾" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "把新添加的种子放在已完成任务之上" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "停止做种需要分享率达到:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "当种子达到最大分享率时自动从列表中删除" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "当作种时间结束后停止继续作种" - -#: glade/preferences_dialog.glade:1120 -msgid "Number of hours" -msgstr "小时数" - -#: glade/preferences_dialog.glade:1142 -msgid "Automatically clear torrents that reach the max seed time" -msgstr "到达最大作种时间后自动清除种子" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "正在做种" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "正在做种" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "每秒尝试连接的最大数量。太高的数值可能会导致某些便宜的路由器崩溃。-1为无限制。" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "每秒最大尝试连接数:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "全局最大上传通道。-1为无限制。" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "全局最大上传速度。-1为无限制。" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "全局最大下载速度。-1为无限制。" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "最大下载速度(KiB/s):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "全局最大连接数。-1为无限制。" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "最大连接数:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "最大上传速度(KiB/s):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "最大上传通道:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "最大半开连接数。过高的值可能会使某些低廉的路由器崩溃。设为-1则无限制。" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "最大半开连接数:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "全局带宽使用情况" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "每个种子的最大上传通道。-1为无限制。" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "每个种子的最大连接数。-1为无限制。" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "每个种子的带宽使用情况" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "带宽" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "影响常规BT用户" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "用代理连接伙伴" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "端口" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "服务器" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"无\n" -"Socks4\n" -"Socks5\n" -"Socks5/需要认证\n" -"HTTP\n" -"HTTP/需要认证" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "密码" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "用户名" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "代理类型" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "用代理连接伙伴" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "用代理连接Tracker" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "用代理连接Tracker" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "用代理连接DHT" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "用代理连接DHT" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "用代理连接Web种子" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "用代理连接Web种子" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "代理" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "启用系统托盘图标" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "关闭后最小化到系统托盘" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "启动后放入系统托盘" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "从系统托盘打开时,需要输入密码" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "密码:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "系统托盘" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "使用高级进度条(稍微多消耗一点CPU/内存)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "细节进度条" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "Deluge会自动检查我们的服务器,当有新版本发布时会通知您" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "自动报告新版本" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "升级" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"请把您的Python和PyGTK版本号、操作系统和处理器型号发给我们,\n" -"以帮助改进Deluge。一定不会发送多余的信息。" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "系统信息" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "其他" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "强制重新检查(_F)" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "继续(_S)" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "暂停(_P)" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "删除种子(_R)" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "Tracker选项(_T)" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "更新Tracker(_U)" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "编辑Trackers(_E)" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "去除Tracker(_S)" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "队列(_Q)" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "顶部(_T)" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "上移(_U)" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "下移(_D)" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "底部(_B)" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "打开下载目录(_O)" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "显示Deluge(_S)" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "全部继续(_R)" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "全部暂停(_P)" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "限制下载速度(_D)" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "限制上传速度(_U)" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "退出(_Q)" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "编辑Tracker" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "正在编辑Tracker" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge文件选择" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "种子将不会在DHT网络上发布" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "设置私人标记" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "首次运行配置" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"本向导将帮助您按照您的喜好设置Deluge。如果您初次接触Deluge,请注意Deluge的大部分功能和特性都来自于插件,这些插件可以通过点击编辑菜单或在" -"工具栏上找到。" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge需要一定范围的端口来尝试侦听入口连接。BT默认端口号是6881-" -"6889,然而,大多数ISP会禁用这些端口,因此您最好选择在49152和65535之间的其他端口。或者,您可以让Deluge自动为您选择随机端口。" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "使用随机端口 (_R)" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "您是想让Deluge自动下载到预定的位置,还是想每次都指定下载文件的位置?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "询问在哪儿保存每个文件" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "将所有下载的文件保存在: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "请选择上传速度,依此我们将自动为下面的设置提出建议" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "最大活动种子数:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "您的上行速度:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"将您的Python和PyGTK的版本,操作系统和处理器类型发送给我们以帮助\n" -"我们改进Deluge。绝对不会发送任何其他信息。" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"无法指定浏览器。请确保你安装了python-gnome2-" -"extras或尝试在/usr/lib/firefox设置你的LD_LIBRARY_PATH以及MOZILLA_FIVE_HOME环境变量" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/秒" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "无限制" - -#: src/interface.py:325 -msgid "Activated" -msgstr "活动的" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "其他..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "下载速度(KiB/s):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "上传速度(KiB/s):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge已被锁定" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge已被密码保护。\n" -"如要显示Deluge窗口,请输入您的密码" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "无穷大" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "未知" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "名称" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "估计剩余时间" - -#: src/interface.py:651 -msgid "Avail." -msgstr "可用" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "分享率" - -#: src/interface.py:760 -msgid "Choose a directory to switch torrent source to" -msgstr "选择一个目录来交换种子资源" - -#: src/interface.py:764 -msgid "Delete the old torrent source?" -msgstr "删除旧的种子源?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "%s已暂停" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "已排队%s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "新版本Deluge发布。您想现在浏览我们的下载网站吗?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "连接" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "下载" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "上传" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge BT客户端" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "请选择文件的保存目录" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "添加该种子时遇到错误,您的种子文件可能已损坏。" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "不明种子副本错误。" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "没有足够的剩余空间来完成你的下载" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "需要空间:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "可用空间:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "从URL添加种子" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "输入种子的URL以供下载" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "警告:该种子的所有文件都将会被删除!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "是否确定删除所有作种的种子?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "已入队列" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "正在检查" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "正在连接" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "正在下载元数据" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "正在下载" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "已完成" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "正在分配存储空间" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "所需空间" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "磁盘空间不足,不能继续下载。" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "发送通告" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "通告正常" - -#: src/core.py:774 -msgid "Alert" -msgstr "提示" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP代码" - -#: src/core.py:776 -msgid "times in a row" -msgstr "一连串的时间点" - -#: src/core.py:788 -msgid "Warning" -msgstr "警告" - -#: src/files.py:77 -msgid "Filename" -msgstr "文件名" - -#: src/files.py:82 -msgid "Priority" -msgstr "优先级" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"仅当设置为完全分配磁盘空间才可以设置文件优先级。\n" -"请将您的设置修改为禁用紧凑分配,然后删除并重新添加该种子。" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "插件" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "已启用" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge为自由软件,您可依据自由软件基金会所发表的GNU通用公共\n" -"授权条款,对本程序再次发布和/或修改,无论您依据的是本授权的第\n" -"2版,或(取决于您)任一日后发行的版本。Deluge是基于使用目的而\n" -"加以发布,但不负任何担保责任,亦无对适售性或特定目的适用性所\n" -"为的默示性担保。详情请参照GNU通用公共授权。您应已收到附随\n" -"Deluge的GNU通用公共授权的副本,但如果没有,请致信\n" -"Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, \n" -"MA 02110-1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "选择种子文件" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "种子文件" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "所有文件" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "外部命令" - -#: src/common.py:207 -msgid "not found" -msgstr "未找到" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"下载并加载不同的 IP 黑名单。\n" -"\n" -"目前本插件支持 PeerGuardian(二进制和文件),\n" -"SafePeer 和 eMule 列表。但不支持 7zip 格式的 PeerGuardian 规则。\n" -"文件可以是指定的URL或者本地文件。\n" -"\n" -"wiki上有提供下载:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian 文本 (已解压缩)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP 列表 (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer 文本 (zip 格式)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "不能下载URL" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "不能打开过滤列表文件" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "错误的文件类型或损坏的过滤列表文件。" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "已导入" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP地址" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "过滤列表" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "项" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "过滤列表URL地址" - -#: plugins/BlocklistImport/ui.py:52 -msgid "Download new blocklist every" -msgstr "下载新的黑名单每隔" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "天" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "安装并加载黑名单" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "导入" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "完成" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "发现压缩包格式异常:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "我们并没有得到预期的gzip文件,或者该文件可能已损坏。请编辑您的过滤列表首选项" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "无效引导" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "无效magic代码" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "无效版本" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "为种子设置一个你预期的分享率" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "预期分享率 (_D)" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "未设置 (_N)" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "未设置" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "预计分享率" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"该插件可以显示下载该种子的客户,并且可以显示他们的ip,国籍,客户端,完成率和上传下载速率。\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP地址" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "客户端" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "完成百分比" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "种子创建者" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "该种子只包含一个文件" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "文件:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "该种子将包含一个目录" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "文件夹:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "种子文件另存为:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "加载一个种子到 Deluge 以做种" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "添加一个种子到队列" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "种子文件" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "Trackers" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "Web种子" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "评论" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "种子创建者" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "设置私有标记" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "较小的块文件容量,可提高传输效率,但会增大\".torrent\"文件" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "块大小" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "高级" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "种子创建插件" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "新增种子 (_N)" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "新增种子" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "创建种子" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "文件另存为..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "你必须为种子选择一个来源" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "你必须选择一个文件以保存该种子。" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "种子提示插件首选项" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "启用事件声音(需要pygame,Win32平台不可用)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "启用闪烁托盘图标" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "启用弹出通告(需要python-notify,Win32平台不可用)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "当完成种子时闪烁托盘图标并且(或者)弹出一个提示" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "种子完成" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"网络状况监视器\n" -"\n" -"作者:Kripkenstein" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[健康度: 好]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "事件日志选项" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "启用日志文件" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "日志文件" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "连接被阻止" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "阻止完成" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "阻止下载" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "分块已完成" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "已下载文件已移动" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "Tracker 警告" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "Tracker 警告" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "Tracker 回复" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "Tracker 通告" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "快速恢复拒绝错误" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "用户禁止错误" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "Hash验证错误" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "文件错误" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "无效请求" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "连接用户信息" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "种子完成" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "选择事件记录到日志" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"添加选择事件日志的标签。\n" -"\n" -"事件信息来自于libtorrent提示。\n" -"如果你想让这些字符串翻译成你的语言,\n" -"你需要将问题报告给libtorrent而非deluge。\n" -"\n" -"至于日志文件,日志将被保存到一个日志文件夹,因为特定的种子将\n" -"被保存到独立的日志文件,文件名与种子同。与特定种子不相关的事件信息\n" -"将被保存到以事件命名的日志中(比如peer_messages.log)。\n" -"日志文件中的事件信息含时间戳。\n" -"由用户负责清理日志。\n" -"\n" -"0.2版本\n" -"事件现已截断显示。日志文件则不同。\n" -"新的事件现于顶部显示。\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "事件日志" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "事件信息: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "种子: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "连接用户信息" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "ip地址: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "客户: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "分块索引: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "状态代码: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "时间线 " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "阻止索引: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "连接速度: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "限制每个种子的速度" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "种子下载速度 (_D)" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "种子上传速度 (_S)" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "种子上传速度 (KiB/s):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "种子下载速度 (KiB/s):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"网络统计图插件\n" -"\n" -"作者:Kripkenstein" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "图表" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "进度" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "打开文件时有错误发生" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"该插件可以显示种子内的文件并允许您分别设置他们的优先级,以及选择那些您需要或者不需要下载的文件。\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "文件" - -#: plugins/MoveTorrent/__init__.py:22 -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"本插件允许用户将种子移动到不同的目录而无须删除并重新添加种子。该特性可以通过右键单击种子文件找到。\n" -"另外,它还可以将完成的种子自动移动到不同的文件夹。\n" -"注意:文件当前只能被移动到同一个分区内。" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "移动种子(_M)" - -#: plugins/MoveTorrent/__init__.py:82 -msgid "_Switch Torrent Source" -msgstr "交换种子源(_S)" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "选择要把文件移动到的目录" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "" -"你不能将种子移动到其他分区。请检查你的首选项。另外,你不能将一个种子文件移动到当前目录,也不能在某种子的所有文件都创建完毕之前就移动该种子的文件。" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "把下载完的文件移动到:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "取消" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "确定" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "本插件允许用户追加Web种子" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "添加Web种子 (_A)" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "添加Web种子" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "网址:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "下载限制:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "上传限制:" - -#: plugins/Scheduler/plugin.py:115 -msgid "Active torrents:" -msgstr "活动的种子:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "上存通道" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "做大连接数:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "计划设置" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "绿色表示上限,黄色表示下限,红色表示停止" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "如果一个限制被设为-1,那么它表示无限制。" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "Web界面设置" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "端口号" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "新密码" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "新密码(确认)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "模板" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "按钮风格" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "缓存模板" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "文本和图像" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "仅图像" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "仅文字" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "已确认密码 <> 新密码\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "翻译" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "选择一个url或一个种子,不能同时选择。" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "无数据。" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "刷新率必须 > 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "# 的文件" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "关于" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "添加种子" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "应用" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "自动刷新:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "健康度" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "设置" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "调试:数据丢弃" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "删除已下载的文件" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "禁用" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "已下载" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "启用" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "错误" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "估计剩余时间" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "登录" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "注销" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "下次通告" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "关闭" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "密码无效,请重输" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "全部暂停" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "块" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "队列向上移动" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "队列位置" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "队列向下移动" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "再次通告" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "刷新页面每隔:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "删除种子" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "全部继续" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "设置" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "设置超时" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "速度" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "开始:" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "提交" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "种子列表" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "总共大小" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "Tracker" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "Tracker 状态" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "上传种子" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "已上传" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "网址" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "秒" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "Feed将会按升级间隔自动下载。" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "Feed必须手动刷新" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "已禁用" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "刷新间隔" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "网址" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "类型" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "Feed" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "信息" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "样式" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "从" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "季度" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "节" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -#, fuzzy -msgid "Thru" -msgstr "全部" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "历史限制" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "不匹配" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "年" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "月" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "日" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "测试" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "将种子放在队列顶部" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "设置为暂停状态" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "匹配后删除过滤器" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "下载" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "替换" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "样式" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "链接重写" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "文件将被保存在Deluge的默认文件夹内,如未设置,则会出现一个提示。" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge默认" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "文件将会自动下载到指定的文件夹" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "选择:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "输出" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "过滤器" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "在Deluge工具栏上显示FlexRSS图标" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "在工具栏上显示图标" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "界面" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "Feed将在单独的线程里被获取和解读。程序不会被阻碍,但可能会不稳定。" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "线程化(实验阶段)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "获取Feed" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "域" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "路径" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "数值" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "设置" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "管理搜索插件" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "名称:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"入名称和URL来添加新的搜索引擎。名称请输入搜索引擎所用的名称,URL请输入搜索页的url。用户的搜索队列会替换这个URL里${query}中的任何实例。" -"\n" -"例如,Google搜索是:\n" -"名字:Google\n" -"URL: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "帮助" - -#: plugins/Search/__init__.py:37 -msgid "Search for torrents anonymously" -msgstr "匿名搜索种子" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "搜索字符串" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "请选择一个搜索引擎" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "管理搜索引擎" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "搜索 " diff --git a/po/zh_TW.po b/po/zh_TW.po deleted file mode 100644 index 8d2fcbf10..000000000 --- a/po/zh_TW.po +++ /dev/null @@ -1,2940 +0,0 @@ -# Chinese (Taiwan) translation for deluge -# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006 -# This file is distributed under the same license as the deluge package. -# FIRST AUTHOR , 2006. -# -msgid "" -msgstr "" -"Project-Id-Version: Deluge VERSION\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2008-04-21 18:40-0500\n" -"PO-Revision-Date: 2008-06-06 09:18+0000\n" -"Last-Translator: Jacky Yeung \n" -"Language-Team: Jose Sun \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2008-06-27 22:00+0000\n" -"X-Generator: Launchpad (build Unknown)\n" -"X-Poedit-Country: Taiwan\n" -"X-Poedit-Language: Chinese\n" -"X-Poedit-SourceCharset: utf-8\n" - -#~ msgid "D/L" -#~ msgstr "下載" - -#~ msgid "U/L" -#~ msgstr "上傳" - -#~ msgid "Share %" -#~ msgstr "分享率" - -#~ msgid "path" -#~ msgstr "路徑" - -#~ msgid "size" -#~ msgstr "大小" - -#~ msgid "offset" -#~ msgstr "前置量" - -#~ msgid "download?" -#~ msgstr "確定要下載?" - -#~ msgid "IP" -#~ msgstr "IP 位址" - -#~ msgid "Connections: " -#~ msgstr "連接數: " - -#~ msgid "Download Speed:" -#~ msgstr "下載速度:" - -#~ msgid "Upload Speed:" -#~ msgstr "上傳速度:" - -#~ msgid "Select Torrent" -#~ msgstr "請選擇種子" - -#~ msgid "infinity" -#~ msgstr "無限" - -#~ msgid "1 second" -#~ msgstr "1 秒鐘" - -#~ msgid "1 minute" -#~ msgstr "1 分鐘" - -#~ msgid "minutes" -#~ msgstr "分" - -#~ msgid "1 hour" -#~ msgstr "1 小時" - -#~ msgid "hours" -#~ msgstr "時" - -#~ msgid "1 day" -#~ msgstr "1 日" - -#~ msgid "1 week" -#~ msgstr "1 週" - -#~ msgid "weeks" -#~ msgstr "週" - -#~ msgid "Search string" -#~ msgstr "搜尋字串" - -#~ msgid "Add a Torrent" -#~ msgstr "新增種子" - -#~ msgid "Deluge Support _Forums" -#~ msgstr "Deluge 支援論壇 (_F)" - -#~ msgid "Force Pause/Resume Torrent" -#~ msgstr "強制 暫停/恢復 下載" - -#~ msgid "Open the online support forums in your web browser" -#~ msgstr "在瀏覽器內開啟線上支援論壇" - -#~ msgid "Show/Hide the Details Pane" -#~ msgstr "顯示/隱藏詳細訊息面板" - -#~ msgid "Update Tracker" -#~ msgstr "更新伺服器" - -#~ msgid "Bandwidth (KB/s):" -#~ msgstr "頻寬 (KB/s):" - -#~ msgid "Save Location:" -#~ msgstr "儲存位置:" - -#~ msgid "Sharing:" -#~ msgstr "分享:" - -#~ msgid "Automatically stop seeding torrents when their share ratio reaches:" -#~ msgstr "當分享率達到這數值時自動停止作種:" - -#~ msgid "Maximum Download Rate:" -#~ msgstr "最大下載頻寬:" - -#~ msgid "Maximum Upload Rate:" -#~ msgstr "最大上傳頻寬:" - -#~ msgid "Maximum number of Downloads:" -#~ msgstr "最大同時下載數:" - -#~ msgid "Maximum number of Uploads:" -#~ msgstr "最大同時上傳數:" - -#~ msgid "Save all downloads to:" -#~ msgstr "儲存所有下載至:" - -#~ msgid "Select a save location for each download" -#~ msgstr "為每個下載選擇儲存位置" - -#~ msgid "gtk-add" -#~ msgstr "新增" - -#~ msgid "gtk-remove" -#~ msgstr "移除" - -#~ msgid "Force Pause" -#~ msgstr "強制暫停" - -#~ msgid "Update Trackers" -#~ msgstr "更新伺服器" - -#~ msgid "Paused" -#~ msgstr "已暫停" - -#~ msgid "Waiting to check" -#~ msgstr "等待測試" - -#~ msgid "Downloading (T?)" -#~ msgstr "正在連線 (T?)" - -#~ msgid "Downloading Meta" -#~ msgstr "下載資訊" - -#~ msgid "N/A" -#~ msgstr "N/A" - -#~ msgid "INF" -#~ msgstr "INF" - -#~ msgid "Hash failed" -#~ msgstr "雜湊失敗" - -#~ msgid "Peer banned" -#~ msgstr "已列入黑名單的端點" - -#~ msgid "Fastresume rejected" -#~ msgstr "快速恢復遭駁回" - -#~ msgid "Event" -#~ msgstr "事件" - -#~ msgid "translator-credits" -#~ msgstr "" -#~ "如對翻譯有任何意見,請送一封電子郵件給以下地址,會盡快回覆您:Cheng-Wei Chien \n" -#~ "\n" -#~ "Launchpad Contributions:\n" -#~ " Accord Tsai https://launchpad.net/~accordtsai\n" -#~ " Chien Cheng Wei https://launchpad.net/~cwchien\n" -#~ " Jacky Yeung https://launchpad.net/~xphk\n" -#~ " Jose Sun https://launchpad.net/~josesun\n" -#~ " Justzupi https://launchpad.net/~justzupi\n" -#~ " Neil Lin https://launchpad.net/~neillin\n" -#~ " Ronmi https://launchpad.net/~ronmi\n" -#~ " josé https://launchpad.net/~jlgdot369\n" -#~ " kevintyk https://launchpad.net/~kevintyk" - -#~ msgid "Translate This Application..." -#~ msgstr "翻譯這個應用程式..." - -#, no-c-format -#~ msgid "" -#~ "Add a new search engine by entering a Name and a URL. For Name, enter the " -#~ "name of the search engine to be used. For URL, enter the url of the seach " -#~ "page. The user's search query will be added to the end of the url, or " -#~ "replace any instances of %%query%% in the URL.\n" -#~ "For example, a Google search would be:\n" -#~ "Name: Google\n" -#~ "URL: http://www.google.com/search?hl=en" -#~ msgstr "" -#~ "輸入一組名稱和網址即可新增搜尋引擎。前者為搜尋引擎的名稱。後者則是搜尋頁面的網址。使用者的搜尋字串會被加到網址的末端,或是取代其中的 %%query%% " -#~ "字樣。\n" -#~ "例如:新增 Google 搜尋將會是:\n" -#~ "名稱:Google\n" -#~ "網址:http://www.google.com/search?hl=en" - -#~ msgid "Are you sure you want to quit Deluge?" -#~ msgstr "您確定要結束 Deluge?" - -#~ msgid "You have " -#~ msgstr "您有 " - -#~ msgid " active torrent" -#~ msgstr " 下載中的種子" - -#~ msgid "s" -#~ msgstr "們" - -#~ msgid ". Pressing 'Yes' will close Deluge and stop all torrent activity." -#~ msgstr "。點選 '確定' 將結束 Deluge 並停止所有下載。" - -#~ msgid "Loaded torrents from previous session" -#~ msgstr "已從上個作業階段載入種子" - -#~ msgid "No torrent is selected" -#~ msgstr "尚未選擇種子" - -#~ msgid "Enter the URL of the .torrent file to open:" -#~ msgstr "請輸入要開啟的種子檔網址:" - -#~ msgid "No plugin is selected" -#~ msgstr "尚未選擇插件" - -#~ msgid "You must activate a plugin before configuring it" -#~ msgstr "您必須先啟用該插件才能設定它" - -#~ msgid "no information is listed for this plugin" -#~ msgstr "沒有此插件的資訊" - -#~ msgid "The torrent file does not contain valid information." -#~ msgstr "種子檔資訊是無效的。" - -#~ msgid "A filesystem error occurred when trying to open the torrent file." -#~ msgstr "試著開啟此種子檔時發生檔案系統錯誤。" - -#~ msgid "The selected torrent is already present in the system." -#~ msgstr "所選的種子已在系統中。" - -#~ msgid "N-A" -#~ msgstr "N-A" - -#~ msgid "Yes" -#~ msgstr "確定" - -#~ msgid "No" -#~ msgstr "取消" - -#~ msgid " is updating its tracker" -#~ msgstr " 正在更新它的伺服器" - -#~ msgid "Mark 'Do Not Download'" -#~ msgstr "標記為 '不下載'" - -#~ msgid "Mark 'Download'" -#~ msgstr "標記為 '下載'" - -#~ msgid "Downloaded this session:" -#~ msgstr "這次作業階段共下載:" - -#~ msgid "Percentage Done:" -#~ msgstr "完成率:" - -#~ msgid "Total Downloaded:" -#~ msgstr "總共下載:" - -#~ msgid "Total Uploaded:" -#~ msgstr "總共上傳:" - -#~ msgid "Tracker Response:" -#~ msgstr "伺服器回應:" - -#~ msgid "Uploaded This Session:" -#~ msgstr "這次作業階段共上傳:" - -#~ msgid "Use compact storage allocation:" -#~ msgstr "使用壓縮儲存:" - -#~ msgid "Add a Torrent from File..." -#~ msgstr "從檔案新增種子 ..." - -#~ msgid "Add a Torrent from URL..." -#~ msgstr "從網址新增種子 ..." - -#~ msgid "New Torrent..." -#~ msgstr "新增種子 ..." - -#~ msgid "Queue Torrent to Bottom" -#~ msgstr "將種子排入佇列末端" - -#~ msgid "Remove selected Torrent" -#~ msgstr "移除所選的種子" - -#~ msgid "_Manage Plugins" -#~ msgstr "管理插件 (_M)" - -#~ msgid "gtk-about" -#~ msgstr "關於" - -#~ msgid "Advanced Network Options:" -#~ msgstr "進階網路選項:" - -#~ msgid "Storage:" -#~ msgstr "大小:" - -#~ msgid "TCP Port:" -#~ msgstr "TCP 埠:" - -#~ msgid "Active port:" -#~ msgstr "啟用的埠:" - -#~ msgid "Mainline DHT" -#~ msgstr "連接 DHT (分散式雜湊表) 網絡" - -#~ msgid "Maximum number of connections:" -#~ msgstr "最大容許連接數:" - -#~ msgid "Test Port" -#~ msgstr "測試連接埠" - -#~ msgid "Try from:" -#~ msgstr "測試從:" - -#~ msgid "Use compact storage allocation (save space)" -#~ msgstr "使用壓縮儲存 (節省空間)" - -#~ msgid "" -#~ "Warning - any change to these settings will only come into effect after a " -#~ "restart!" -#~ msgstr "警告 - 對這些設定做的任何改變將在重新啟動後生效!" - -#~ msgid "" -#~ "Are you sure you want to remove the selected torrent(s) from Deluge?" -#~ msgstr "您確定要從 Deluge 中移除所選的種子(們)?" - -#, no-c-format -#~ msgid "" -#~ "CPU % must persist for following time (seconds) before either of the above:" -#~ msgstr "上述事件啟動前,CPU 使用率必須持續顯示多少時間 (秒) :" - -#~ msgid "CPU Monitor Configuration" -#~ msgstr "CPU 監控設定" - -#, no-c-format -#~ msgid "Fatal CPU % (Deluge will be shut down):" -#~ msgstr "危險的 CPU 使用率 (Deluge 即將關閉):" - -#, no-c-format -#~ msgid "Warning CPU % (notification only):" -#~ msgstr "警告的 CPU 使用率 (僅顯示通知):" - -#~ msgid "" -#~ "Notifications of the following Severity Level and above will be displayed:" -#~ msgstr "危急程度高於此級的通知將會顯示:" - -#~ msgid "Popup Notifier Configuration" -#~ msgstr "彈出式通知設定" - -#~ msgid "Popup Notification" -#~ msgstr "彈出式通知" - -#~ msgid "SafeDeluge Configuration" -#~ msgstr "安全模式 Deluge 設定" - -#~ msgid "Use custom blocklist URL:" -#~ msgstr "使用自訂的黑名單網址:" - -#~ msgid "Use default blocklist URL" -#~ msgstr "使用預設的黑名單網址" - -#~ msgid "Connections:" -#~ msgstr "連接數:" - -#~ msgid "Download:" -#~ msgstr "下載:" - -#~ msgid "Upload:" -#~ msgstr "上傳:" - -#~ msgid "There is suspicious activity in" -#~ msgstr "發現可疑的活動於" - -#~ msgid "The torrent may be poisoned by the RIAA/MPAA. Found" -#~ msgstr "此種子檔可能被植入 RIAA/MPAA。發現" - -#~ msgid "at prevalence" -#~ msgstr "於向外連線時" - -#~ msgid "Shutting down Deluge immediately." -#~ msgstr "正在緊急關閉 Deluge。" - -#~ msgid "Shutting down Deluge immediately (CPU overload)." -#~ msgstr "正在緊急關閉 Deluge (CPU 負載過高)。" - -#~ msgid "CPU usage warning: more than" -#~ msgstr "CPU 使用率警告:超過" - -#~ msgid "CPU usage for" -#~ msgstr "CPU 使用率於" - -#~ msgid "No incoming connections" -#~ msgstr "沒有可下載的連線" - -#~ msgid "" -#~ "No incoming connections: you may be behind a firewall or router. Perhaps you " -#~ "need to forward the relevant ports." -#~ msgstr "沒有可下載的連線:您的主機可能在防火牆或路由器後面。或許您必須延伸相關連接埠。" - -#~ msgid "Health: OK" -#~ msgstr "健康度:良好" - -#~ msgid "" -#~ "PopupNotifier: not all necessary dependencies are installed. To install " -#~ "them, on Ubuntu run: apt-get python-notify notification-daemon" -#~ msgstr "" -#~ "彈出式通知:必須的相依套件未全部安裝。若要安裝,於 Ubuntu 上執行:sudo apt-get install python-notify " -#~ "notification-daemon" - -#~ msgid "" -#~ "PopupNotifier: Cannot initialize pynotify, no notifications will be shown." -#~ msgstr "彈出式通知:無法初始化 pynotify,將不會顯示任何通知。" - -#~ msgid "Informative - can be easily ignored" -#~ msgstr "通知訊息 - 忽略無妨" - -#~ msgid "Warning - may be of interest" -#~ msgstr "警告訊息 - 需要注意" - -#~ msgid "Critical - should never be ignored" -#~ msgstr "緊急訊息 - 不可忽略" - -#~ msgid "Fatal - normal operation will probably not continue" -#~ msgstr "危險訊息 - 可能無法繼續正常運作" - -#~ msgid "Retrieving blocklist from server" -#~ msgstr "從伺服器取得黑名單" - -#~ msgid "Applying SafeDeluge blocklist" -#~ msgstr "套用安全模式 Deluge 的黑名單" - -#~ msgid "The torrent file does not contain all necessary valid information." -#~ msgstr "種子檔資訊部份是無效的。" - -#: glade/delugegtk.glade:29 plugins/WebUi/scripts/template_strings.py:4 -msgid "Add Torrent" -msgstr "新增種子" - -#: glade/delugegtk.glade:30 plugins/WebUi/scripts/template_strings.py:3 -msgid "Add" -msgstr "新增" - -#: glade/delugegtk.glade:43 glade/dgtkpopups.glade:6 -msgid "Remove Torrent" -msgstr "移除種子" - -#: glade/delugegtk.glade:44 plugins/WebUi/scripts/template_strings.py:43 -msgid "Remove" -msgstr "移除" - -#: glade/delugegtk.glade:56 -msgid "Clear Seeding Torrents" -msgstr "清除作種中種子" - -#: glade/delugegtk.glade:57 -msgid "Clear" -msgstr "清除" - -#: glade/delugegtk.glade:79 -msgid "Start or Resume Torrent" -msgstr "開始或繼續下載" - -#: glade/delugegtk.glade:80 plugins/WebUi/scripts/template_strings.py:45 -msgid "Resume" -msgstr "恢復" - -#: glade/delugegtk.glade:93 -msgid "Pause Torrent" -msgstr "暫停下載" - -#: glade/delugegtk.glade:94 plugins/WebUi/scripts/template_strings.py:32 -msgid "Pause" -msgstr "暫停" - -#: glade/delugegtk.glade:106 -msgid "Queue Torrent Up" -msgstr "佇列中種子上移" - -#: glade/delugegtk.glade:107 plugins/WebUi/scripts/template_strings.py:59 -msgid "Up" -msgstr "往上移" - -#: glade/delugegtk.glade:120 -msgid "Queue Torrent Down" -msgstr "佇列中種子下移" - -#: glade/delugegtk.glade:121 plugins/WebUi/scripts/template_strings.py:17 -msgid "Down" -msgstr "往下移" - -#: glade/delugegtk.glade:142 -msgid "Change Deluge preferences" -msgstr "更改 Deluge 偏好設定" - -#: glade/delugegtk.glade:143 -msgid "Preferences" -msgstr "偏好設定" - -#: glade/delugegtk.glade:156 glade/dgtkpopups.glade:210 -#: glade/preferences_dialog.glade:2844 -msgid "Plugins" -msgstr "外掛模組" - -#: glade/delugegtk.glade:186 -msgid "_File" -msgstr "_檔案" - -#: glade/delugegtk.glade:193 glade/tray_menu.glade:61 -msgid "_Add Torrent" -msgstr "新增種子(_A)" - -#: glade/delugegtk.glade:208 -msgid "Add _URL" -msgstr "新增網址(_U)" - -#: glade/delugegtk.glade:216 -msgid "_Clear Completed" -msgstr "清除已完成檔案(_C)" - -#: glade/delugegtk.glade:249 -msgid "_Edit" -msgstr "_編輯" - -#: glade/delugegtk.glade:274 -msgid "Plu_gins" -msgstr "外掛模組(_G)" - -#: glade/delugegtk.glade:302 -msgid "_Torrent" -msgstr "種子(_T)" - -#: glade/delugegtk.glade:309 -msgid "_View" -msgstr "檢視(_V)" - -#: glade/delugegtk.glade:317 -msgid "_Toolbar" -msgstr "工具列(_T)" - -#: glade/delugegtk.glade:326 -msgid "_Details" -msgstr "詳細資訊(_D)" - -#: glade/delugegtk.glade:335 -msgid "_Columns" -msgstr "欄位(_C)" - -#: glade/delugegtk.glade:343 src/interface.py:630 src/files.py:80 -#: plugins/WebUi/scripts/template_strings.py:51 -msgid "Size" -msgstr "大小" - -#: glade/delugegtk.glade:352 src/interface.py:634 -#: plugins/FlexRSS/FlexRSS.glade:138 -msgid "Status" -msgstr "狀態" - -#: glade/delugegtk.glade:361 src/interface.py:636 -#: plugins/WebUi/scripts/template_strings.py:47 -msgid "Seeders" -msgstr "種子數" - -#: glade/delugegtk.glade:370 src/interface.py:639 -#: plugins/TorrentPeers/__init__.py:85 -#: plugins/WebUi/scripts/template_strings.py:34 -msgid "Peers" -msgstr "用戶數" - -#: glade/delugegtk.glade:379 src/interface.py:642 src/interface.py:1237 -#: src/interface.py:1268 plugins/TorrentPeers/tab_peers.py:89 -#: plugins/WebUi/scripts/template_strings.py:18 -msgid "Down Speed" -msgstr "下載速度" - -#: glade/delugegtk.glade:388 src/interface.py:645 src/interface.py:1238 -#: src/interface.py:1269 plugins/TorrentPeers/tab_peers.py:91 -#: plugins/WebUi/scripts/template_strings.py:60 -msgid "Up Speed" -msgstr "上傳速度" - -#: glade/delugegtk.glade:397 -msgid "Time Remaining" -msgstr "剩餘時間" - -#: glade/delugegtk.glade:406 plugins/WebUi/scripts/template_strings.py:9 -msgid "Availability" -msgstr "可得性" - -#: glade/delugegtk.glade:415 plugins/WebUi/scripts/template_strings.py:50 -msgid "Share Ratio" -msgstr "分享率" - -#: glade/delugegtk.glade:432 -msgid "_Help" -msgstr "_說明" - -#: glade/delugegtk.glade:440 -msgid "Donate to Deluge Development" -msgstr "捐助 Deluge Development" - -#: glade/delugegtk.glade:441 -msgid "_Donate" -msgstr "_捐助" - -#: glade/delugegtk.glade:458 -msgid "_Homepage" -msgstr "首頁(_H)" - -#: glade/delugegtk.glade:475 -msgid "_FAQ" -msgstr "常見問題(_F)" - -#: glade/delugegtk.glade:492 -msgid "_Community" -msgstr "社群(_C)" - -#: glade/delugegtk.glade:515 -msgid "Help translate this application" -msgstr "協助翻譯本程式" - -#: glade/delugegtk.glade:516 -msgid "_Translate This Application..." -msgstr "翻譯本程式(_T)..." - -#: glade/delugegtk.glade:539 -msgid "Runs the first-time configuration wizard" -msgstr "執行初次組態精靈" - -#: glade/delugegtk.glade:540 -msgid "_Run Configuration Wizard" -msgstr "初次組態精靈(_R)" - -#: glade/delugegtk.glade:795 -msgid "Downloaded:" -msgstr "已下載: " - -#: glade/delugegtk.glade:809 -msgid "Uploaded:" -msgstr "已上傳: " - -#: glade/delugegtk.glade:827 -msgid "Seeders:" -msgstr "種子數: " - -#: glade/delugegtk.glade:845 -msgid "Share Ratio:" -msgstr "分享率: " - -#: glade/delugegtk.glade:864 glade/delugegtk.glade:883 -msgid "Speed:" -msgstr "速度: " - -#: glade/delugegtk.glade:904 -msgid "Peers:" -msgstr "用戶數: " - -#: glade/delugegtk.glade:925 -msgid "ETA:" -msgstr "剩餘時間: " - -#: glade/delugegtk.glade:942 -msgid "Pieces:" -msgstr "區塊:" - -#: glade/delugegtk.glade:980 -msgid "Availability:" -msgstr "可得性: " - -#: glade/delugegtk.glade:1021 -msgid "Statistics" -msgstr "統計" - -#: glade/delugegtk.glade:1063 -msgid "# of files:" -msgstr "檔案總數: " - -#: glade/delugegtk.glade:1126 -msgid "Total Size:" -msgstr "總大小:" - -#: glade/delugegtk.glade:1147 -msgid "Tracker:" -msgstr "伺服器: " - -#: glade/delugegtk.glade:1168 -msgid "Tracker Status:" -msgstr "伺服器狀態: " - -#: glade/delugegtk.glade:1189 -msgid "Next Announce:" -msgstr "下次發佈: " - -#: glade/delugegtk.glade:1211 -msgid "Name:" -msgstr "名稱: " - -#: glade/delugegtk.glade:1277 -msgid "Path:" -msgstr "路徑: " - -#: glade/delugegtk.glade:1312 -msgid "Torrent Info" -msgstr "種子資訊" - -#: glade/delugegtk.glade:1338 plugins/WebUi/scripts/template_strings.py:15 -msgid "Details" -msgstr "詳細資訊" - -#: glade/dgtkpopups.glade:42 -msgid "" -"Are you sure you want to remove the selected " -"torrent(s) from Deluge?" -msgstr "你確定要從 Deluge 中刪除所選的種子嗎?" - -#: glade/dgtkpopups.glade:66 -msgid "Delete downloaded files" -msgstr "刪除已下載檔案" - -#: glade/dgtkpopups.glade:89 plugins/WebUi/scripts/template_strings.py:13 -msgid "Delete .torrent file" -msgstr "刪除 .torrent 檔" - -#: glade/dgtkpopups.glade:156 -msgid "Show/Hide" -msgstr "顯示/隱藏" - -#: glade/dgtkpopups.glade:164 -msgid "Add a Torrent..." -msgstr "新增種子..." - -#: glade/dgtkpopups.glade:180 -msgid "Clear Finished" -msgstr "清除已完成下載" - -#: glade/file_tab_menu.glade:11 -msgid "_Open File" -msgstr "開啟檔案(_O)" - -#: glade/file_tab_menu.glade:33 -msgid "Select All" -msgstr "全選" - -#: glade/file_tab_menu.glade:48 -msgid "Unselect All" -msgstr "取消全選" - -#: glade/file_tab_menu.glade:68 src/core.py:103 -msgid "Don't download" -msgstr "不下載" - -#: glade/file_tab_menu.glade:83 src/core.py:104 -msgid "Normal" -msgstr "一般" - -#: glade/file_tab_menu.glade:98 src/core.py:105 -msgid "High" -msgstr "高" - -#: glade/file_tab_menu.glade:113 src/core.py:106 -msgid "Highest" -msgstr "最高" - -#: glade/merge_dialog.glade:7 -msgid "Deluge Merge Tracker Lists" -msgstr "Deluge 合併伺服器清單" - -#: glade/merge_dialog.glade:23 -msgid "" -"Torrent already detected in Deluge, would you like to merge the tracker " -"lists?" -msgstr "Deluge 中已有此種子,你要合併伺服器清單嗎?" - -#: glade/preferences_dialog.glade:9 -msgid "Deluge Preferences" -msgstr "Deluge 偏好設定" - -#: glade/preferences_dialog.glade:58 -msgid "Ask where to save each download" -msgstr "每次都問我要存到何處" - -#: glade/preferences_dialog.glade:76 glade/preferences_dialog.glade:103 -#: glade/preferences_dialog.glade:188 glade/wizard.glade:187 -#: plugins/MoveTorrent/movetorrent.glade:35 -msgid "Select A Folder" -msgstr "選擇一個資料夾" - -#: glade/preferences_dialog.glade:90 -msgid "Store all torrent files in:" -msgstr "儲存所有種子檔案於:" - -#: glade/preferences_dialog.glade:115 glade/preferences_dialog.glade:116 -msgid "Store all downloads in:" -msgstr "儲存所有下載至:" - -#: glade/preferences_dialog.glade:137 -msgid "Download Location" -msgstr "下載位置" - -#: glade/preferences_dialog.glade:173 -msgid "Autoload all torrent files in:" -msgstr "自動載入此目錄的種子檔案:" - -#: glade/preferences_dialog.glade:205 -msgid "Autoload" -msgstr "自動載入" - -#: glade/preferences_dialog.glade:241 glade/preferences_dialog.glade:258 -#: glade/wizard.glade:237 glade/wizard.glade:478 -msgid "" -"The number of active torrents that Deluge will run. Set to -1 for unlimited." -msgstr "Deluge 執行時活動的種子數。若不限制,請設為 -1。" - -#: glade/preferences_dialog.glade:243 -msgid "Maximum simultaneous active torrents:" -msgstr "最大同時活動種子數:" - -#: glade/preferences_dialog.glade:280 glade/preferences_dialog.glade:281 -#: glade/preferences_dialog.glade:302 -msgid "Enable selecting files for torrents before loading" -msgstr "載入前可選擇要下載的檔案" - -#: glade/preferences_dialog.glade:303 -msgid "Only show if torrent has more than 1 file" -msgstr "只在種子含有一個以上的檔案時顯示" - -#: glade/preferences_dialog.glade:319 glade/preferences_dialog.glade:320 -msgid "Prioritize first and last pieces of files in torrent" -msgstr "先下載種子的頭尾部份" - -#: glade/preferences_dialog.glade:335 -msgid "Start torrents in paused state" -msgstr "將新加入的種子設為暫停" - -#: glade/preferences_dialog.glade:351 -msgid "Torrents" -msgstr "種子" - -#: glade/preferences_dialog.glade:390 -msgid "" -"Full allocation preallocates all of the space that is needed for the torrent " -"and prevents disk fragmentation" -msgstr "預先分配完整的檔案空間,避免產生不連續片段" - -#: glade/preferences_dialog.glade:391 -msgid "Use Full Allocation" -msgstr "使用完整檔案分配" - -#: glade/preferences_dialog.glade:413 -msgid "Compact allocation only allocates space as needed" -msgstr "依下載大小分配檔案空間" - -#: glade/preferences_dialog.glade:414 -msgid "Use Compact Allocation" -msgstr "使用緊密檔案分配" - -#: glade/preferences_dialog.glade:434 -msgid "Allocation" -msgstr "檔案分配" - -#: glade/preferences_dialog.glade:458 -msgid "Downloads" -msgstr "下載" - -#: glade/preferences_dialog.glade:502 -msgid "" -"Please Note - Changes to these settings will only be applied the next " -"time Deluge is restarted." -msgstr "請注意 - 變更這些設定要在 Deluge 下次啟動後才會套用。" - -#: glade/preferences_dialog.glade:545 glade/wizard.glade:48 -msgid "From:" -msgstr "從:" - -#: glade/preferences_dialog.glade:568 glade/wizard.glade:66 -msgid "To:" -msgstr "至:" - -#: glade/preferences_dialog.glade:594 -msgid "Deluge will automatically choose a different port to use every time." -msgstr "Deluge 每次啟動時隨機選擇一個通訊埠。" - -#: glade/preferences_dialog.glade:595 -msgid "Random Ports" -msgstr "隨機通訊埠" - -#: glade/preferences_dialog.glade:612 -msgid "Test Active Port" -msgstr "測試可用通訊埠" - -#: glade/preferences_dialog.glade:638 -msgid "TCP" -msgstr "TCP" - -#: glade/preferences_dialog.glade:650 -msgid "Active Port:" -msgstr "啟用的通訊埠:" - -#: glade/preferences_dialog.glade:663 -msgid "0000" -msgstr "0000" - -#: glade/preferences_dialog.glade:702 -msgid "Distributed hash table may improve the amount of active connections." -msgstr "分散式雜湊表 (DHT) 可以增加有效的連線數。" - -#: glade/preferences_dialog.glade:703 -msgid "Enable Mainline DHT" -msgstr "啟用 Mainline DHT" - -#: glade/preferences_dialog.glade:716 -msgid "DHT" -msgstr "DHT" - -#: glade/preferences_dialog.glade:751 -msgid "Universal Plug and Play" -msgstr "通用隨插即用" - -#: glade/preferences_dialog.glade:752 -msgid "UPnP" -msgstr "UPnP" - -#: glade/preferences_dialog.glade:766 -msgid "NAT Port Mapping Protocol" -msgstr "NAT 通訊埠對映協定" - -#: glade/preferences_dialog.glade:767 -msgid "NAT-PMP" -msgstr "NAT-PMP" - -#: glade/preferences_dialog.glade:782 glade/preferences_dialog.glade:783 -msgid "Peer Exchange" -msgstr "用戶交換" - -#: glade/preferences_dialog.glade:799 -msgid "Local Peer Discovery" -msgstr "近端用戶搜尋" - -#: glade/preferences_dialog.glade:814 -msgid "Network Extras" -msgstr "網路附加功能" - -#: glade/preferences_dialog.glade:855 -msgid "Inbound:" -msgstr "向內連線:" - -#: glade/preferences_dialog.glade:864 glade/preferences_dialog.glade:886 -msgid "" -"Disabled\n" -"Enabled\n" -"Forced" -msgstr "" -"停用\n" -"啟用\n" -"強制啟用" - -#: glade/preferences_dialog.glade:877 -msgid "Outbound:" -msgstr "向外連線:" - -#: glade/preferences_dialog.glade:904 -msgid "Prefer to encrypt the entire stream" -msgstr "傾向於加密整個串流" - -#: glade/preferences_dialog.glade:917 -msgid "Level:" -msgstr "層級:" - -#: glade/preferences_dialog.glade:931 -msgid "" -"Handshake\n" -"Full Stream\n" -"Either" -msgstr "" -"交握階段\n" -"整個串流\n" -"兩者皆可" - -#: glade/preferences_dialog.glade:954 -msgid "Encryption" -msgstr "加密" - -#: glade/preferences_dialog.glade:984 -msgid "Network" -msgstr "網路" - -#: glade/preferences_dialog.glade:1025 -msgid "Queue torrents to bottom when they begin seeding" -msgstr "開始作種時將種子排到佇列底端" - -#: glade/preferences_dialog.glade:1037 -msgid "Queue new torrents above completed ones" -msgstr "將新種子排在已完成種子之前" - -#: glade/preferences_dialog.glade:1053 -msgid "Stop seeding torrents when their share ratio reaches:" -msgstr "當分享率達到下列的值就停止作種:" - -#: glade/preferences_dialog.glade:1089 -msgid "Automatically clear torrents that reach the max share ratio" -msgstr "自動清除已達到最大分享率的種子" - -#: glade/preferences_dialog.glade:1105 -msgid "Stop seeding torrents when their seed time reaches:" -msgstr "當" - -#: glade/preferences_dialog.glade:1120 -#, fuzzy -msgid "Number of hours" -msgstr "小時" - -#: glade/preferences_dialog.glade:1142 -#, fuzzy -msgid "Automatically clear torrents that reach the max seed time" -msgstr "當到達最大做種時間時自動清除torrents" - -#: glade/preferences_dialog.glade:1158 -msgid "Seeding" -msgstr "作種中" - -#: glade/preferences_dialog.glade:1187 src/core.py:94 -#: plugins/WebUi/webserver_common.py:201 -msgid "Seeding" -msgstr "作種中" - -#: glade/preferences_dialog.glade:1233 glade/preferences_dialog.glade:1249 -msgid "" -"The maximum number of connection attempts per second. A high value may " -"crash some cheap routers. Set -1 for unlimited." -msgstr "每秒可嘗試的最大連線數,數值太高可能會讓某些廉價路由器當機。若不限制,請設為 -1。" - -#: glade/preferences_dialog.glade:1251 -msgid "Maximum Connection Attempts per Second:" -msgstr "每秒嘗試的最大連線數:" - -#: glade/preferences_dialog.glade:1262 glade/wizard.glade:257 -#: glade/wizard.glade:318 -msgid "The maximum upload slots for all torrents. Set -1 for unlimited." -msgstr "最大總上傳區段。若不限制,請設為 -1。" - -#: glade/preferences_dialog.glade:1279 glade/preferences_dialog.glade:1365 -#: glade/preferences_dialog.glade:1385 glade/wizard.glade:277 -#: glade/wizard.glade:341 -msgid "The maximum upload speed for all torrents. Set -1 for unlimited." -msgstr "最大總上傳速度。若不限制,請設為 -1。" - -#: glade/preferences_dialog.glade:1298 glade/preferences_dialog.glade:1315 -msgid "The maximum download speed for all torrents. Set -1 for unlimited." -msgstr "最大總下載速度。若不限制,請設為 -1。" - -#: glade/preferences_dialog.glade:1317 -msgid "Maximum Download Speed (KiB/s):" -msgstr "最大總下載速度 (KiB/秒):" - -#: glade/preferences_dialog.glade:1328 glade/preferences_dialog.glade:1347 -#: glade/wizard.glade:297 glade/wizard.glade:364 -msgid "The maximum number of connections allowed. Set -1 for unlimited." -msgstr "允許的最大連線數。若不限制請設為-1。" - -#: glade/preferences_dialog.glade:1349 glade/preferences_dialog.glade:1534 -#: glade/wizard.glade:298 -msgid "Maximum Connections:" -msgstr "最大連線數:" - -#: glade/preferences_dialog.glade:1367 glade/wizard.glade:278 -msgid "Maximum Upload Speed (KiB/s):" -msgstr "最大總上傳速度 (KiB/秒):" - -#: glade/preferences_dialog.glade:1387 glade/preferences_dialog.glade:1515 -#: glade/wizard.glade:258 -msgid "Maximum Upload Slots:" -msgstr "最大上傳區段:" - -#: glade/preferences_dialog.glade:1405 glade/preferences_dialog.glade:1421 -#: glade/wizard.glade:434 glade/wizard.glade:455 -msgid "" -"The maximum half-open connections. A high value may crash some cheap " -"routers. Set -1 for unlimited." -msgstr "最大半開連線數,數值太高可能會讓某些廉價路由器當機。若不限制,請設為 -1。" - -#: glade/preferences_dialog.glade:1407 glade/wizard.glade:435 -msgid "Maximum Half-Open Connections:" -msgstr "最大半開連線數:" - -#: glade/preferences_dialog.glade:1441 -msgid "Global Bandwidth Usage" -msgstr "全域頻寬設定" - -#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1513 -msgid "The maximum upload slots per torrent. Set -1 for unlimited." -msgstr "各種子最大上傳區段。若不限制,請設為 -1。" - -#: glade/preferences_dialog.glade:1495 glade/preferences_dialog.glade:1532 -msgid "The maximum number of connections per torrent. Set -1 for unlimited." -msgstr "各種子最大連線數。若不限制,請設為 -1。" - -#: glade/preferences_dialog.glade:1547 -msgid "Per Torrent Bandwidth Usage" -msgstr "各種子頻寬設定" - -#: glade/preferences_dialog.glade:1573 -msgid "Bandwidth" -msgstr "頻寬" - -#: glade/preferences_dialog.glade:1619 glade/preferences_dialog.glade:1814 -#: glade/preferences_dialog.glade:2009 glade/preferences_dialog.glade:2204 -msgid "Affects regular bittorrent peers" -msgstr "這會影響正常的 BT 用戶端" - -#: glade/preferences_dialog.glade:1620 -msgid "Peer Proxy" -msgstr "用戶端 Proxy" - -#: glade/preferences_dialog.glade:1665 glade/preferences_dialog.glade:1860 -#: glade/preferences_dialog.glade:2055 glade/preferences_dialog.glade:2250 -msgid "Port" -msgstr "通訊埠" - -#: glade/preferences_dialog.glade:1678 glade/preferences_dialog.glade:1873 -#: glade/preferences_dialog.glade:2068 glade/preferences_dialog.glade:2263 -msgid "Server" -msgstr "伺服器" - -#: glade/preferences_dialog.glade:1719 glade/preferences_dialog.glade:1914 -#: glade/preferences_dialog.glade:2109 glade/preferences_dialog.glade:2304 -msgid "" -"None\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 W/ Auth\n" -"HTTP\n" -"HTTP W/ Auth" -msgstr "" -"無\n" -"Socksv4\n" -"Socksv5\n" -"Socksv5 需要認證\n" -"HTTP\n" -"HTTP 需要認證" - -#: glade/preferences_dialog.glade:1735 glade/preferences_dialog.glade:1930 -#: glade/preferences_dialog.glade:2125 glade/preferences_dialog.glade:2320 -#: plugins/WebUi/scripts/template_strings.py:30 -msgid "Password" -msgstr "密碼" - -#: glade/preferences_dialog.glade:1746 glade/preferences_dialog.glade:1941 -#: glade/preferences_dialog.glade:2136 glade/preferences_dialog.glade:2331 -msgid "Username" -msgstr "使用者名稱" - -#: glade/preferences_dialog.glade:1757 glade/preferences_dialog.glade:1952 -#: glade/preferences_dialog.glade:2147 glade/preferences_dialog.glade:2342 -msgid "Proxy type" -msgstr "Proxy 類型" - -#: glade/preferences_dialog.glade:1782 -msgid "Peer Proxy" -msgstr "用戶端 Proxy" - -#: glade/preferences_dialog.glade:1815 -msgid "Tracker Proxy" -msgstr "伺服器 Proxy" - -#: glade/preferences_dialog.glade:1977 -msgid "Tracker Proxy" -msgstr "伺服器 Proxy" - -#: glade/preferences_dialog.glade:2010 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2172 -msgid "DHT Proxy" -msgstr "DHT Proxy" - -#: glade/preferences_dialog.glade:2205 -msgid "Web Seed Proxy" -msgstr "網路種子 Proxy" - -#: glade/preferences_dialog.glade:2367 -msgid "Web Seed Proxy" -msgstr "網路種子 Proxy" - -#: glade/preferences_dialog.glade:2394 -msgid "Proxies" -msgstr "Proxy" - -#: glade/preferences_dialog.glade:2423 -msgid "Enable system tray icon" -msgstr "啟用系統列圖示" - -#: glade/preferences_dialog.glade:2440 -msgid "Minimize to tray on close" -msgstr "關閉時最小化到系統列" - -#: glade/preferences_dialog.glade:2460 -msgid "Start in tray" -msgstr "啟動於系統列" - -#: glade/preferences_dialog.glade:2485 -msgid "Password protect system tray" -msgstr "縮小到系統列的密碼保護" - -#: glade/preferences_dialog.glade:2509 -msgid "Password:" -msgstr "密碼:" - -#: glade/preferences_dialog.glade:2553 -msgid "System Tray" -msgstr "系統列" - -#: glade/preferences_dialog.glade:2582 -msgid "Use the advanced progress bar (uses slightly more CPU/RAM)" -msgstr "使用進階的進度列 (會佔用多一點 CPU 及記憶體)" - -#: glade/preferences_dialog.glade:2593 -msgid "Detailed Progress Bar" -msgstr "詳細進度列" - -#: glade/preferences_dialog.glade:2627 -msgid "" -"Deluge will check our servers and will tell you if a newer version has been " -"released" -msgstr "Deluge 會定時檢查伺服器以通知有無新版本發佈" - -#: glade/preferences_dialog.glade:2628 -msgid "Be alerted about new releases" -msgstr "新版本發佈時通知" - -#: glade/preferences_dialog.glade:2645 -msgid "Updates" -msgstr "更新" - -#: glade/preferences_dialog.glade:2675 -msgid "" -"Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"回傳電腦上 Python 及 PyGTK 版本、\n" -"作業系統及處理器類型,協助我們改善 Deluge。\n" -"除此之外不會回傳其他資訊。" - -#: glade/preferences_dialog.glade:2688 -msgid "System Information" -msgstr "系統資訊" - -#: glade/preferences_dialog.glade:2714 -#: plugins/EventLogging/event_logging_preferences.glade:52 -#: plugins/EventLogging/tab_log.py:218 -msgid "Other" -msgstr "其他" - -#: glade/torrent_menu.glade:11 -msgid "_Force Recheck" -msgstr "強制重新檢查(_F)" - -#: glade/torrent_menu.glade:33 -msgid "Re_sume" -msgstr "續傳(_S)" - -#: glade/torrent_menu.glade:50 -msgid "_Pause" -msgstr "暫停(_P)" - -#: glade/torrent_menu.glade:72 -msgid "_Remove Torrent" -msgstr "移除種子(_R)" - -#: glade/torrent_menu.glade:95 -msgid "_Tracker Options" -msgstr "伺服器選項(_T)" - -#: glade/torrent_menu.glade:104 -msgid "_Update Tracker" -msgstr "_更新伺服器" - -#: glade/torrent_menu.glade:121 -msgid "_Edit Trackers" -msgstr "編輯伺服器網址(_E)" - -#: glade/torrent_menu.glade:138 -msgid "_Scrape Tracker" -msgstr "向伺服器請求用戶(_S)" - -#: glade/torrent_menu.glade:164 -msgid "_Queue" -msgstr "佇列(_Q)" - -#: glade/torrent_menu.glade:174 -msgid "_Top" -msgstr "移至頂端(_T)" - -#: glade/torrent_menu.glade:190 -msgid "_Up" -msgstr "往上移(_U)" - -#: glade/torrent_menu.glade:206 -msgid "_Down" -msgstr "往下移(_D)" - -#: glade/torrent_menu.glade:222 -msgid "_Bottom" -msgstr "移至底端(_B)" - -#: glade/torrent_menu.glade:251 -msgid "_Open Containing Folder" -msgstr "開啟下載資料夾(_O)" - -#: glade/tray_menu.glade:12 -msgid "_Show Deluge" -msgstr "顯示 Deluge 視窗(_S)" - -#: glade/tray_menu.glade:21 -msgid "_Resume All" -msgstr "全部續傳(_R)" - -#: glade/tray_menu.glade:38 -msgid "_Pause All" -msgstr "全部暫停(_P)" - -#: glade/tray_menu.glade:84 -msgid "_Download Speed Limit" -msgstr "下載速限(_D)" - -#: glade/tray_menu.glade:100 -msgid "_Upload Speed Limit" -msgstr "上傳速限(_D)" - -#: glade/tray_menu.glade:122 -msgid "_Quit" -msgstr "結束(_Q)" - -#: glade/edit_trackers.glade:9 -msgid "Edit Trackers" -msgstr "編輯伺服器" - -#: glade/edit_trackers.glade:19 -msgid "Tracker Editing" -msgstr "伺服器編輯" - -#: glade/files_dialog.glade:8 -msgid "Deluge File Selection" -msgstr "Deluge 檔案選擇" - -#: glade/files_dialog.glade:42 -msgid "Torrent will not be distributed on the trackerless (DHT) network" -msgstr "此種子將不會出現於無伺服器 (DHT) 網路上" - -#: glade/files_dialog.glade:43 -msgid "Set the private flag" -msgstr "設定私人標記" - -#: glade/wizard.glade:10 -msgid "First Launch Configuration" -msgstr "初次執行組態設定" - -#: glade/wizard.glade:20 -msgid "" -"This wizard will help you set up Deluge to your liking. If you are new to " -"Deluge, please note that most of Deluge's functionality and features come in " -"the form of plugins, which can be accessed by clicking on Plugins in the " -"Edit menu or the toolbar." -msgstr "" -"本精靈將會協助你設定 Deluge 到最佳狀態。如果你是初次使用 Deluge,請注意 Deluge 有很多功能是以外掛模組 (Plugin) " -"形式提供的,你可以到「編輯>外掛模組」中設定。" - -#: glade/wizard.glade:36 -msgid "" -"Deluge needs a range of ports that it will try to listen to for incoming " -"connections. The default ports for bittorrent are 6881-6889, however, most " -"ISPs block those ports, so you're encouraged to pick others, between 49152 " -"and 65535. Alternatively, you can have Deluge automatically pick random " -"ports for you." -msgstr "" -"Deluge 需要好幾個通訊埠監聽連入的連線。Bittorrent 預設的通訊埠為 6881-6889,但是很多 ISP " -"會封鎖這些通訊埠,你可以自己選擇從 49152 到 65535 間的任意通訊埠來避免此問題,或者也可以讓 Deluge 自動隨機選擇通訊埠。" - -#: glade/wizard.glade:88 -msgid "Use _Random Ports" -msgstr "使用隨機通訊埠 (_R)" - -#: glade/wizard.glade:116 -msgid "" -"Would you like Deluge to automatically download to a predefined location, or " -"would you like to specify the download location every time?" -msgstr "你要讓 Deluge 自動將下載的檔案放到指定的位置,或是每次下載時自己選擇呢?" - -#: glade/wizard.glade:141 -msgid "Ask where to save each file" -msgstr "每次都問我要存到何處" - -#: glade/wizard.glade:165 -msgid "Store all downloads in: " -msgstr "儲存所有下載至: " - -#: glade/wizard.glade:215 -msgid "" -"Please select the upload speed of your connection, which we will then use to " -"automatically make suggestions for the settings below" -msgstr "請選擇你網路的上傳速度,我們會依你選擇的速度提供建議的設定值" - -#: glade/wizard.glade:238 -msgid "Maximum Active Torrents:" -msgstr "最大活動種子數:" - -#: glade/wizard.glade:386 -msgid "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" -msgstr "" -"28.8k\n" -"56k\n" -"64k\n" -"96k\n" -"128k\n" -"192k\n" -"256k\n" -"384k\n" -"512k\n" -"640k\n" -"768k\n" -"1Mbit\n" -"2Mbit\n" -"10Mbit\n" -"20Mbit\n" -"40Mbit\n" -"50Mbit\n" -"100Mbit" - -#: glade/wizard.glade:419 -msgid "Your Upload Line Speed:" -msgstr "你的上傳速度:" - -#: glade/wizard.glade:506 -msgid "" -"_Help us improve Deluge by sending us your Python and PyGTK\n" -"versions, OS and processor types. Absolutely no other\n" -"information is sent." -msgstr "" -"回傳電腦上 Python 及 PyGTK 版本、\n" -"作業系統及處理器類型,協助我們改善 Deluge。\n" -"除此之外不會回傳其他資訊。" - -#: src/interface.py:235 -msgid "" -"Unable to state browser. Make sure you have python-gnome2-extras installed " -"or try setting your LD_LIBRARY_PATH and MOZILLA_FIVE_HOME environment " -"variables to /usr/lib/firefox" -msgstr "" -"無法啟動瀏覽器,請確認您已安裝python-gnome2-" -"extras或嘗試將您的LD_LIBRARY_PATH和MOZILLA_FIVE_HOME環境變數設定至/usr/lib/firefox" - -#: src/interface.py:295 src/interface.py:301 src/interface.py:382 -#: src/interface.py:410 plugins/SpeedLimiter/__init__.py:84 -#: plugins/SpeedLimiter/__init__.py:94 plugins/SpeedLimiter/__init__.py:138 -#: plugins/SpeedLimiter/__init__.py:170 -msgid "KiB/s" -msgstr "KiB/秒" - -#: src/interface.py:322 src/interface.py:383 src/interface.py:411 -#: src/interface.py:1219 src/interface.py:1226 src/interface.py:1231 -#: src/interface.py:1259 src/interface.py:1261 -#: plugins/SpeedLimiter/__init__.py:139 plugins/SpeedLimiter/__init__.py:171 -msgid "Unlimited" -msgstr "未限制" - -#: src/interface.py:325 -msgid "Activated" -msgstr "正在下載" - -#: src/interface.py:374 src/interface.py:386 src/interface.py:414 -#: plugins/DesiredRatio/__init__.py:116 plugins/SpeedLimiter/__init__.py:142 -#: plugins/SpeedLimiter/__init__.py:174 -msgid "Other..." -msgstr "其他..." - -#: src/interface.py:391 -msgid "Download Speed (KiB/s):" -msgstr "下載速度 (KiB/秒):" - -#: src/interface.py:419 -msgid "Upload Speed (KiB/s):" -msgstr "上傳速度 (KiB/秒):" - -#: src/interface.py:448 -msgid "Deluge is locked" -msgstr "Deluge 已鎖住" - -#: src/interface.py:451 -msgid "" -"Deluge is password protected.\n" -"To show the Deluge window, please enter your password" -msgstr "" -"Deluge 已受密碼保護。\n" -"若要顯示 Deluge 視窗,請輸入您的密碼" - -#: src/interface.py:598 src/common.py:74 -msgid "Infinity" -msgstr "無限" - -#: src/interface.py:610 -msgid "Unknown" -msgstr "未知" - -#: src/interface.py:627 plugins/WebUi/scripts/template_strings.py:27 -#: plugins/FlexRSS/FlexRSS.glade:179 plugins/FlexRSS/FlexRSS.glade:373 -#: plugins/FlexRSS/FlexRSS.glade:1475 plugins/Search/__init__.py:79 -msgid "Name" -msgstr "名稱" - -#: src/interface.py:648 plugins/WebUi/scripts/template_strings.py:21 -msgid "ETA" -msgstr "預計完成時間" - -#: src/interface.py:651 -msgid "Avail." -msgstr "可得性" - -#: src/interface.py:653 plugins/WebUi/scripts/template_strings.py:40 -msgid "Ratio" -msgstr "分享率" - -#: src/interface.py:760 -#, fuzzy -msgid "Choose a directory to switch torrent source to" -msgstr "選擇切換torrent來源目錄" - -#: src/interface.py:764 -#, fuzzy -msgid "Delete the old torrent source?" -msgstr "刪除舊的torrent來源?" - -#: src/interface.py:953 -#, python-format -msgid "Paused %s" -msgstr "已暫停 %s" - -#: src/interface.py:955 -#, python-format -msgid "Queued %s" -msgstr "佇列 %s" - -#: src/interface.py:1069 -msgid "" -"There is a newer version of Deluge. Would you like to be taken to our " -"download site?" -msgstr "Deluge 有新版本,你要連到網站下載嗎?" - -#: src/interface.py:1237 plugins/WebUi/scripts/template_strings.py:11 -msgid "Connections" -msgstr "連接數" - -#: src/interface.py:1255 -msgid "DHT" -msgstr "DHT" - -#: src/interface.py:1264 plugins/TorrentCreator/__init__.py:149 -msgid "Deluge" -msgstr "Deluge" - -#: src/interface.py:1264 plugins/WebUi/scripts/template_strings.py:19 -msgid "Download" -msgstr "下載" - -#: src/interface.py:1265 plugins/WebUi/scripts/template_strings.py:61 -msgid "Upload" -msgstr "上傳" - -#: src/interface.py:1268 -msgid "Deluge Bittorrent Client" -msgstr "Deluge BT 用戶端" - -#: src/interface.py:1345 -msgid "Choose a download directory" -msgstr "請選取一個下載目錄" - -#: src/interface.py:1394 -msgid "" -"An error occured while trying to add the torrent. It's possible your " -".torrent file is corrupted." -msgstr "嘗試新增種子時發生錯誤,可能是種子檔案已損毀。" - -#: src/interface.py:1422 -msgid "Unknown duplicate torrent error." -msgstr "未知的重複種子檔案錯誤。" - -#: src/interface.py:1427 -msgid "There is not enough freedisk space to complete your download." -msgstr "沒有足夠空間可以完成您的下載。" - -#: src/interface.py:1428 src/core.py:642 -msgid "Space Needed:" -msgstr "所需磁碟空間:" - -#: src/interface.py:1429 src/core.py:642 -msgid "Available Space:" -msgstr "可用磁碟空間:" - -#: src/interface.py:1462 -msgid "Add torrent from URL" -msgstr "從網址新增種子" - -#: src/interface.py:1466 -msgid "Enter the URL of the .torrent to download" -msgstr "請輸入種子檔案的網址" - -#: src/interface.py:1529 -msgid "Warning - all downloaded files for this torrent will be deleted!" -msgstr "警告 - 此種子下載的所有檔案將被刪除!" - -#: src/interface.py:1545 -msgid "Are you sure that you want to remove all seeding torrents?" -msgstr "你確定要移除所有作種中的種子嗎?" - -#: src/core.py:88 plugins/WebUi/webserver_common.py:195 -msgid "Queued" -msgstr "已排入佇列" - -#: src/core.py:89 plugins/WebUi/webserver_common.py:196 -msgid "Checking" -msgstr "檢查中" - -#: src/core.py:90 plugins/WebUi/webserver_common.py:197 -msgid "Connecting" -msgstr "連接中" - -#: src/core.py:91 plugins/WebUi/webserver_common.py:198 -msgid "Downloading Metadata" -msgstr "下載後設資料中" - -#: src/core.py:92 plugins/BlocklistImport/ui.py:136 -#: plugins/WebUi/webserver_common.py:199 -msgid "Downloading" -msgstr "下載中" - -#: src/core.py:93 plugins/WebUi/webserver_common.py:200 -msgid "Finished" -msgstr "已完成" - -#: src/core.py:95 plugins/WebUi/webserver_common.py:202 -msgid "Allocating" -msgstr "正在分配空間" - -#: src/core.py:138 -msgid "bytes needed" -msgstr "所需空間" - -#: src/core.py:640 -msgid "There is not enough free disk space to complete your download." -msgstr "剩餘空間不足以完成您的下載。" - -#: src/core.py:761 -msgid "Announce sent" -msgstr "通告已送出" - -#: src/core.py:765 -msgid "Announce OK" -msgstr "通告完成" - -#: src/core.py:774 -msgid "Alert" -msgstr "警告" - -#: src/core.py:775 -msgid "HTTP code" -msgstr "HTTP 代碼" - -#: src/core.py:776 -msgid "times in a row" -msgstr "連續次數" - -#: src/core.py:788 -msgid "Warning" -msgstr "警告" - -#: src/files.py:77 -msgid "Filename" -msgstr "檔案名稱" - -#: src/files.py:82 -msgid "Priority" -msgstr "優先權" - -#: src/files.py:104 -msgid "" -"File priority can only be set when using full allocation.\n" -"Please change your preference to disable compact allocation, then remove and " -"re-add this torrent." -msgstr "" -"檔案優先權只能於完整檔案分配時設定。\n" -"請到偏好設定中停用「緊密檔案分配」後移除再重新加入此種子。" - -#: src/dialogs.py:66 -msgid "Plugin" -msgstr "外掛模組" - -#: src/dialogs.py:68 plugins/FlexRSS/FlexRSS.glade:104 -msgid "Enabled" -msgstr "已啟用" - -#: src/dialogs.py:445 -msgid "" -"Deluge is free software, you can redistribute it and/or\n" -"modify it under the terms of the GNU General Public\n" -" License as published by the Free Software Foundation,\n" -"either version 2 of the License, or (at your option) any\n" -"later version. Deluge is distributed in the hope that it\n" -"will be useful, but WITHOUT ANY WARRANTY, without even \n" -"the implied warranty of MERCHANTABILITY or FITNESS\n" -"FOR A PARTICULAR PURPOSE. See the GNU General\n" -"Public License for more details. You should have received\n" -"a copy of the GNU General Public License along with\n" -"Deluge, but if not, write to the Free Software Foundation,\n" -" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n" -"1301 USA" -msgstr "" -"Deluge 是自由軟體,你可以在 FSF 發佈的 GPL 第二版或\n" -"未來的版本授權下重新散佈或修改本程式。Deluge 希望能\n" -"幫助大眾但不承擔「任何擔保責任」以及「適售性」和為某\n" -"個「特殊目的的適用性」的默認擔保責任。詳細資訊請見 \n" -"GNU 通用公共授權。你應該會隨 Deluge 程式收到一份 \n" -"GPL 的副本,如果沒有可以向自由軟體基金會索取,\n" -"51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA" - -#: src/dialogs.py:486 -msgid "Choose a .torrent file" -msgstr "請選取一個種子檔案" - -#: src/dialogs.py:491 -msgid "Torrent files" -msgstr "種子檔案" - -#: src/dialogs.py:495 -msgid "All files" -msgstr "所有檔案" - -#: src/common.py:88 -msgid "KiB" -msgstr "KiB" - -#: src/common.py:91 -msgid "MiB" -msgstr "MiB" - -#: src/common.py:94 -msgid "GiB" -msgstr "GiB" - -#: src/common.py:97 -msgid "TiB" -msgstr "TiB" - -#: src/common.py:99 -msgid "PiB" -msgstr "PiB" - -#: src/common.py:206 -msgid "External command" -msgstr "外部命令" - -#: src/common.py:207 -msgid "not found" -msgstr "找不到" - -#: plugins/BlocklistImport/__init__.py:9 -msgid "" -"\n" -"Download and import various IP blocklists.\n" -"\n" -"Currently this plugin can handle PeerGuardian (binary and text),\n" -"SafePeer and Emule lists. PeerGuardian 7zip format files are not\n" -"supported. Files may be specified as URLs or locations on the local\n" -"filesystem.\n" -"\n" -"A page with pointer to blocklist download sites is available on the\n" -"wiki:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" -msgstr "" -"\n" -"下載並匯入不同的 IP 過濾清單。\n" -"\n" -"目前本外掛模組能處理 PeerGuardian(二進制及純文字檔),\n" -"SafePeer 及 Emule 清單。PeerGuardian 7zip 格式檔案尚未支援。\n" -"必須要指定檔案網址或本機所在路徑。\n" -"\n" -"Wiki 上有一頁提供了各個黑名單的下載網站:\n" -"\n" -"http://dev.deluge-torrent.org/wiki/BlocklistPlugin\n" - -#: plugins/BlocklistImport/__init__.py:41 -msgid "PeerGuardian P2B (GZip)" -msgstr "PeerGuardian P2B (GZip)" - -#: plugins/BlocklistImport/__init__.py:42 -msgid "PeerGuardian Text (Uncompressed)" -msgstr "PeerGuardian 文字檔 (未壓縮)" - -#: plugins/BlocklistImport/__init__.py:43 -msgid "Emule IP list (GZip)" -msgstr "Emule IP list (GZip)" - -#: plugins/BlocklistImport/__init__.py:44 -msgid "SafePeer Text (Zipped)" -msgstr "SafePeer 文字檔 (已壓縮)" - -#: plugins/BlocklistImport/__init__.py:118 -msgid "Couldn't download URL" -msgstr "找不到下載網址" - -#: plugins/BlocklistImport/__init__.py:131 -msgid "Couldn't open blocklist file" -msgstr "無法開啟黑名單" - -#: plugins/BlocklistImport/__init__.py:139 plugins/BlocklistImport/text.py:37 -#: plugins/BlocklistImport/text.py:70 plugins/BlocklistImport/text.py:88 -#: plugins/BlocklistImport/text.py:99 -msgid "Wrong file type or corrupted blocklist file." -msgstr "檔案類型錯誤或封鎖清單檔案已損毀。" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "Imported" -msgstr "已匯入" - -#: plugins/BlocklistImport/__init__.py:147 -msgid "IPs" -msgstr "IP" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "Blocklist" -msgstr "黑名單" - -#: plugins/BlocklistImport/__init__.py:190 -msgid "entries" -msgstr "項目" - -#: plugins/BlocklistImport/ui.py:25 -msgid "Blocklist URL" -msgstr "黑名單網址" - -#: plugins/BlocklistImport/ui.py:52 -#, fuzzy -msgid "Download new blocklist every" -msgstr "下載新的封鎖名單" - -#: plugins/BlocklistImport/ui.py:59 -msgid "days" -msgstr "日" - -#: plugins/BlocklistImport/ui.py:123 -msgid "Loading and installing blocklist" -msgstr "載入並安裝黑名單中" - -#: plugins/BlocklistImport/ui.py:147 -msgid "Importing" -msgstr "匯入中" - -#: plugins/BlocklistImport/ui.py:158 -msgid "Complete" -msgstr "已完成" - -#: plugins/BlocklistImport/text.py:129 -msgid "Got format exception for zipfile:" -msgstr "Zip 檔案的格式例外錯誤:" - -#: plugins/BlocklistImport/peerguardian.py:24 -msgid "" -"We were expecting a gzip file, but didn't get that, or possibly the file is " -"corrupt. Please edit your Blocklist preferences" -msgstr "程式無法解壓縮 gzip 檔,檔案可能已損毀,請編輯你的封鎖清單設定。" - -#: plugins/BlocklistImport/peerguardian.py:32 -msgid "Invalid leader" -msgstr "Leader 無效" - -#: plugins/BlocklistImport/peerguardian.py:36 -msgid "Invalid magic code" -msgstr "Magic Code 無效" - -#: plugins/BlocklistImport/peerguardian.py:41 -msgid "Invalid version" -msgstr "版本無效" - -#: plugins/DesiredRatio/__init__.py:22 -msgid "Set the desired ratio for a torrent." -msgstr "設定種子的預計分享率。" - -#: plugins/DesiredRatio/__init__.py:77 -msgid "_Desired Ratio" -msgstr "預計分享率(_D)" - -#: plugins/DesiredRatio/__init__.py:81 -msgid "_Not Set" -msgstr "不設定(_N)" - -#: plugins/DesiredRatio/__init__.py:113 -msgid "Not Set" -msgstr "不設定" - -#: plugins/DesiredRatio/__init__.py:120 -msgid "Desired Ratio" -msgstr "預計分享率" - -#: plugins/TorrentPeers/__init__.py:34 -msgid "" -"\n" -"This shows you the peers associated with each torrent and shows you their " -"ip, country, client, percent complete and upload and download speeds.\n" -msgstr "" -"\n" -"顯示各個種子連接用戶端的 IP、國家、下載程式、下載進度及上下傳速度。\n" - -#: plugins/TorrentPeers/tab_peers.py:84 -msgid "IP Address" -msgstr "IP 位址" - -#: plugins/TorrentPeers/tab_peers.py:86 -msgid "Client" -msgstr "用戶端" - -#: plugins/TorrentPeers/tab_peers.py:87 -msgid "Percent Complete" -msgstr "下載進度" - -#: plugins/TorrentCreator/torrentcreator.glade:9 -msgid "Torrent Creator" -msgstr "種子製作器" - -#: plugins/TorrentCreator/torrentcreator.glade:104 -msgid "This torrent will be made from a single file" -msgstr "以單一檔案建立種子" - -#: plugins/TorrentCreator/torrentcreator.glade:105 -msgid "File:" -msgstr "檔案:" - -#: plugins/TorrentCreator/torrentcreator.glade:121 -msgid "This torrent will be made from a directory" -msgstr "以目錄中的檔案建立種子" - -#: plugins/TorrentCreator/torrentcreator.glade:122 -msgid "Folder:" -msgstr "資料夾:" - -#: plugins/TorrentCreator/torrentcreator.glade:139 -msgid "Source" -msgstr "來源" - -#: plugins/TorrentCreator/torrentcreator.glade:185 -msgid "Save Torrent File As:" -msgstr "另存種子檔案:" - -#: plugins/TorrentCreator/torrentcreator.glade:238 -msgid "Load this torrent into Deluge for seeding" -msgstr "載入此種子到 Deluge 中作種" - -#: plugins/TorrentCreator/torrentcreator.glade:239 -msgid "Add new torrent to queue" -msgstr "加入新種子到佇列中" - -#: plugins/TorrentCreator/torrentcreator.glade:258 -msgid "Torrent File" -msgstr "種子檔案" - -#: plugins/TorrentCreator/torrentcreator.glade:306 -msgid "Trackers" -msgstr "發佈伺服器" - -#: plugins/TorrentCreator/torrentcreator.glade:353 -msgid "Web Seeds" -msgstr "網頁種子" - -#: plugins/TorrentCreator/torrentcreator.glade:400 -msgid "Comments" -msgstr "備註" - -#: plugins/TorrentCreator/torrentcreator.glade:437 -msgid "Author" -msgstr "作者" - -#: plugins/TorrentCreator/torrentcreator.glade:476 -msgid "Set Private Flag" -msgstr "設定私人標籤" - -#: plugins/TorrentCreator/torrentcreator.glade:489 -#: plugins/TorrentCreator/torrentcreator.glade:510 -msgid "" -"The smaller the piece sizes, the more efficient the transfers will be, but " -"the actual \".torrent\" file will be larger" -msgstr "片段越小在傳輸時越有效率,但是產生的「.torrent」檔案就會越大" - -#: plugins/TorrentCreator/torrentcreator.glade:490 -msgid "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" -msgstr "" -"32 KiB\n" -"64 KiB\n" -"128 KiB\n" -"256 KiB\n" -"512 KiB\n" -"1024 KiB\n" -"2048 KiB\n" - -#: plugins/TorrentCreator/torrentcreator.glade:512 -msgid "Piece Size:" -msgstr "片段大小:" - -#: plugins/TorrentCreator/torrentcreator.glade:526 -msgid "Advanced" -msgstr "進階" - -#: plugins/TorrentCreator/__init__.py:22 -msgid "A torrent creator plugin" -msgstr "種子製作外掛模組" - -#: plugins/TorrentCreator/__init__.py:51 -msgid "_New Torrent" -msgstr "新種子(_N)" - -#: plugins/TorrentCreator/__init__.py:61 -msgid "New Torrent" -msgstr "新種子" - -#: plugins/TorrentCreator/__init__.py:63 -msgid "Create New Torrent" -msgstr "建立新種子" - -#: plugins/TorrentCreator/__init__.py:99 -msgid "Save file as..." -msgstr "另存新檔..." - -#: plugins/TorrentCreator/__init__.py:121 -msgid "You must select a source for the torrent." -msgstr "你必須選擇種子的來源。" - -#: plugins/TorrentCreator/__init__.py:128 -msgid "You must select a file to save the torrent as." -msgstr "你必須選擇要存為種子的檔案。" - -#: plugins/TorrentNotification/notification_preferences.glade:7 -msgid "Torrent Notification Preferences" -msgstr "種子通知偏好設定" - -#: plugins/TorrentNotification/notification_preferences.glade:32 -msgid "Enable event sound (requires pygame, not available on Win32)" -msgstr "啟用事件音效 (需要 pygame, Win32 無法使用)" - -#: plugins/TorrentNotification/notification_preferences.glade:59 -msgid "Enable blinking tray icon" -msgstr "啟用閃爍系統列圖示" - -#: plugins/TorrentNotification/notification_preferences.glade:69 -msgid "" -"Enable popup notification (requires python-notify, not available on Win32)" -msgstr "啟用彈出視窗提示 (需要 python-notify, Win32 無法使用)" - -#: plugins/TorrentNotification/__init__.py:22 -msgid "" -"Make tray icon blink when torrent finishes downloading and/or popup a " -"notification" -msgstr "當種子完成下載時閃爍系統列圖示或彈出通知視窗" - -#: plugins/TorrentNotification/__init__.py:108 -msgid "Torrent complete" -msgstr "種子下載完成" - -#: plugins/NetworkHealth/__init__.py:36 -msgid "" -"Network Health Monitor plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"網路狀態監視器模組\n" -"\n" -"Kripkenstein 撰寫" - -#: plugins/NetworkHealth/plugin.py:54 -msgid "[Health: OK]" -msgstr "[狀態: OK]" - -#: plugins/EventLogging/event_logging_preferences.glade:7 -msgid "Event Logging Preferences" -msgstr "事件記錄偏好設定" - -#: plugins/EventLogging/event_logging_preferences.glade:28 -msgid "Enable log files" -msgstr "啟用記錄檔案" - -#: plugins/EventLogging/event_logging_preferences.glade:41 -msgid "Log files" -msgstr "記錄檔" - -#: plugins/EventLogging/event_logging_preferences.glade:66 -#: plugins/EventLogging/tab_log.py:210 -msgid "Peer blocked" -msgstr "用戶端已封鎖" - -#: plugins/EventLogging/event_logging_preferences.glade:80 -#: plugins/EventLogging/tab_log.py:200 -msgid "Block finished" -msgstr "區塊已完成" - -#: plugins/EventLogging/event_logging_preferences.glade:94 -#: plugins/EventLogging/tab_log.py:189 -msgid "Block downloading" -msgstr "區塊下載中" - -#: plugins/EventLogging/event_logging_preferences.glade:108 -#: plugins/EventLogging/tab_log.py:179 -msgid "Piece finished" -msgstr "片段已完成" - -#: plugins/EventLogging/event_logging_preferences.glade:122 -#: plugins/EventLogging/tab_log.py:170 -msgid "Storage moved" -msgstr "檔案已移動" - -#: plugins/EventLogging/event_logging_preferences.glade:136 -#: plugins/EventLogging/tab_log.py:161 -msgid "Tracker warning" -msgstr "伺服器警告" - -#: plugins/EventLogging/event_logging_preferences.glade:150 -#: plugins/EventLogging/tab_log.py:150 -msgid "Tracker alert" -msgstr "伺服器提示" - -#: plugins/EventLogging/event_logging_preferences.glade:164 -#: plugins/EventLogging/tab_log.py:141 -msgid "Tracker reply" -msgstr "伺服器回應" - -#: plugins/EventLogging/event_logging_preferences.glade:178 -#: plugins/EventLogging/tab_log.py:132 -msgid "Tracker announce" -msgstr "伺服器通告" - -#: plugins/EventLogging/event_logging_preferences.glade:192 -#: plugins/EventLogging/tab_log.py:123 -msgid "Fastresume rejected error" -msgstr "快速續傳拒絕的錯誤" - -#: plugins/EventLogging/event_logging_preferences.glade:206 -#: plugins/EventLogging/tab_log.py:114 -msgid "Peer ban error" -msgstr "用戶端封鎖的錯誤" - -#: plugins/EventLogging/event_logging_preferences.glade:220 -#: plugins/EventLogging/tab_log.py:104 -msgid "Hash failed error" -msgstr "雜湊失敗的錯誤" - -#: plugins/EventLogging/event_logging_preferences.glade:234 -#: plugins/EventLogging/tab_log.py:95 -msgid "File error" -msgstr "檔案錯誤" - -#: plugins/EventLogging/event_logging_preferences.glade:248 -#: plugins/EventLogging/tab_log.py:86 -msgid "Invalid request" -msgstr "無效的要求" - -#: plugins/EventLogging/event_logging_preferences.glade:262 -msgid "Peer messages" -msgstr "用戶端訊息" - -#: plugins/EventLogging/event_logging_preferences.glade:276 -#: plugins/EventLogging/tab_log.py:70 -msgid "Torrent finished" -msgstr "種子已完成" - -#: plugins/EventLogging/event_logging_preferences.glade:289 -msgid "Select events to log" -msgstr "選擇要記錄的事件" - -#: plugins/EventLogging/__init__.py:22 -msgid "" -"\n" -"Adds a tab with log of selected events.\n" -"\n" -"Event messages come from libtorrent alerts.\n" -"If you want those strings translated to your locale,\n" -"you'll have to report the issue with libtorrent, not deluge.\n" -"\n" -"Regarding the log files, the logs are saved in a log\n" -"directory within the deluge config directory. Event\n" -"messages for specific torrents are saved to individual\n" -"log files named the same as the associated .torrent\n" -"file. Event messages not specific to any torrent are\n" -"saved to logs named after the events\n" -"(eg peer_messages.log).\n" -"Event messages in the log files also include a timestamp.\n" -"The user is responsible to cleanout the logs.\n" -"\n" -"As of v0.2\n" -"Events are now truncated in display. Log files are not.\n" -"New events are now displayed at the top.\n" -msgstr "" -"\n" -"新增一個分頁記錄選擇的事件。\n" -"\n" -"事件訊息來自 libtorrent 的提示。\n" -"如果你想將訊息字串翻譯成你的語言,\n" -"你應該回報錯誤給 libtorrent 而不是 Deluge。\n" -"\n" -"關於記錄檔,記錄檔案都會儲存於 Deluge 組態目錄中\n" -"的 log 目錄中。每個種子特定的訊息則會以對應的 \n" -".torrent 檔名命名個別儲存。非特定的事件訊息則會\n" -"共同用一個檔案 (例: peer_messages.log) 儲存。\n" -"記錄檔中的事件訊息會有時間戳記。\n" -"使用者需要自行清理記錄檔案。\n" -"\n" -"0.2 版本之後的事件訊息太長時會被截斷,但記錄檔中則不會。\n" -"新事件會顯示在頂端。\n" - -#: plugins/EventLogging/__init__.py:89 -msgid "Event Log" -msgstr "事件記錄" - -#: plugins/EventLogging/tab_log.py:70 plugins/EventLogging/tab_log.py:78 -#: plugins/EventLogging/tab_log.py:86 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:104 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:132 plugins/EventLogging/tab_log.py:141 -#: plugins/EventLogging/tab_log.py:150 plugins/EventLogging/tab_log.py:161 -#: plugins/EventLogging/tab_log.py:170 plugins/EventLogging/tab_log.py:179 -#: plugins/EventLogging/tab_log.py:189 plugins/EventLogging/tab_log.py:200 -#: plugins/EventLogging/tab_log.py:210 plugins/EventLogging/tab_log.py:218 -msgid "event message: " -msgstr "事件訊息: " - -#: plugins/EventLogging/tab_log.py:71 plugins/EventLogging/tab_log.py:95 -#: plugins/EventLogging/tab_log.py:105 plugins/EventLogging/tab_log.py:115 -#: plugins/EventLogging/tab_log.py:124 plugins/EventLogging/tab_log.py:133 -#: plugins/EventLogging/tab_log.py:142 plugins/EventLogging/tab_log.py:151 -#: plugins/EventLogging/tab_log.py:162 plugins/EventLogging/tab_log.py:171 -#: plugins/EventLogging/tab_log.py:180 plugins/EventLogging/tab_log.py:190 -#: plugins/EventLogging/tab_log.py:201 -msgid "torrent: " -msgstr "種子: " - -#: plugins/EventLogging/tab_log.py:78 -msgid "Peer message" -msgstr "用戶端訊息" - -#: plugins/EventLogging/tab_log.py:78 plugins/EventLogging/tab_log.py:114 -#: plugins/EventLogging/tab_log.py:211 -msgid "ip address: " -msgstr "IP 位址: " - -#: plugins/EventLogging/tab_log.py:79 plugins/EventLogging/tab_log.py:86 -msgid "client: " -msgstr "用戶端: " - -#: plugins/EventLogging/tab_log.py:106 plugins/EventLogging/tab_log.py:181 -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "piece index: " -msgstr "片段索引: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "status code: " -msgstr "狀態碼: " - -#: plugins/EventLogging/tab_log.py:152 -msgid "Times in a row: " -msgstr "連續次數: " - -#: plugins/EventLogging/tab_log.py:191 plugins/EventLogging/tab_log.py:202 -msgid "block index: " -msgstr "阻擋索引: " - -#: plugins/EventLogging/tab_log.py:192 -msgid "peer speed: " -msgstr "用戶端速度: " - -#: plugins/SpeedLimiter/__init__.py:20 -msgid "Set the desired speed limit per torrent." -msgstr "設定各種子的速度限制。" - -#: plugins/SpeedLimiter/__init__.py:82 -msgid "Torrent _Download Speed" -msgstr "種子下載速度(_D)" - -#: plugins/SpeedLimiter/__init__.py:92 -msgid "Torrent Upload _Speed" -msgstr "種子上傳速度(_S)" - -#: plugins/SpeedLimiter/__init__.py:146 -msgid "Torrent Upload Speed (KiB/s):" -msgstr "種子上傳速度 (KiB/秒):" - -#: plugins/SpeedLimiter/__init__.py:178 -msgid "Torrent Download Speed (KiB/s):" -msgstr "種子下載速度 (KiB/秒):" - -#: plugins/NetworkGraph/__init__.py:36 -msgid "" -"Network Activity Graph plugin\n" -"\n" -"Written by Kripkenstein" -msgstr "" -"網路流量圖模組\n" -"\n" -"Kripkenstein 撰寫" - -#: plugins/NetworkGraph/__init__.py:91 -msgid "Graph" -msgstr "流量圖" - -#: plugins/TorrentFiles/tab_files.py:59 -#: plugins/WebUi/scripts/template_strings.py:36 -msgid "Progress" -msgstr "進度" - -#: plugins/TorrentFiles/tab_files.py:100 -msgid "There was an error trying to launch the file." -msgstr "嘗試開啟檔案時錯誤。" - -#: plugins/TorrentFiles/__init__.py:34 -msgid "" -"\n" -"This plugin shows you the files inside a torrent and allows you to set " -"priorities for them and choose which ones you want or don't want to " -"download.\n" -msgstr "" -"\n" -"本外掛模組會顯示種子中的檔案,並能設定每個檔案的優先權或選擇要下載哪些檔案。\n" - -#: plugins/TorrentFiles/__init__.py:84 -msgid "Files" -msgstr "檔案" - -#: plugins/MoveTorrent/__init__.py:22 -#, fuzzy -msgid "" -"This plugin allows users to move the torrent to a different directory " -"without having to remove and re-add the torrent. This feature can be found " -"by right-clicking on a torrent.\n" -"Furthermore, it allows the user to automatically have finished torrents " -"moved to a different folder.\n" -"Note: Files can currently only be moved within the same partition" -msgstr "" -"本外掛容許使用者在無須移除或重新加入torrent的情況下移動torrent.\n" -"此功能可透過開啟torrent的右鍵選單而達成.\n" -"此外,本功能容許使用者設定把已完成的torrent自動移至不同資料夾.\n" -"注意:檔案目前只能移至相同的硬碟磁區" - -#: plugins/MoveTorrent/__init__.py:75 -msgid "_Move Torrent" -msgstr "移動種子(_M)" - -#: plugins/MoveTorrent/__init__.py:82 -#, fuzzy -msgid "_Switch Torrent Source" -msgstr "_切換torrent來源" - -#: plugins/MoveTorrent/__init__.py:102 -msgid "Choose a directory to move files to" -msgstr "選擇要移動的目的資料夾" - -#: plugins/MoveTorrent/__init__.py:133 -msgid "" -"You cannot move torrent to a different partition. Please check your " -"preferences. Also, you cannot move a torrent's files to the same directory " -"that they are already stored or move a torrent's files before any of its " -"files have actually been created." -msgstr "你無法移動種子到不同的分割區,請重新檢查偏好設定。你也不能移動種子中的檔案到原來的目錄,或是在尚未下載完成前移動檔案。" - -#: plugins/MoveTorrent/movetorrent.glade:25 -msgid "Move completed downloads to:" -msgstr "將已完成的下載移至:" - -#: plugins/MoveTorrent/movetorrent.glade:59 plugins/WebSeed/webseed.glade:65 -msgid "gtk-cancel" -msgstr "gtk-cancel" - -#: plugins/MoveTorrent/movetorrent.glade:71 plugins/WebSeed/webseed.glade:73 -msgid "gtk-ok" -msgstr "gtk-ok" - -#: plugins/WebSeed/__init__.py:22 -msgid "This plugin allows users to add web seeds to their torrents" -msgstr "此外掛模組能讓你附加網路種子到 Torrent 中" - -#: plugins/WebSeed/__init__.py:51 -msgid "_Add Web Seed" -msgstr "加入網路種子(_A)" - -#: plugins/WebSeed/webseed.glade:7 -msgid "Add Web Seed" -msgstr "加入網路種子" - -#: plugins/WebSeed/webseed.glade:29 plugins/Search/searchdlg.glade:91 -msgid "URL:" -msgstr "網址:" - -#: plugins/Scheduler/plugin.py:113 -msgid "Download limit:" -msgstr "下載限制:" - -#: plugins/Scheduler/plugin.py:114 -msgid "Upload limit:" -msgstr "上載限制:" - -#: plugins/Scheduler/plugin.py:115 -#, fuzzy -msgid "Active torrents:" -msgstr "活躍的torrents:" - -#: plugins/Scheduler/plugin.py:116 -msgid "Upload Slots:" -msgstr "上傳連線數:" - -#: plugins/Scheduler/plugin.py:117 -msgid "Max Connections:" -msgstr "最大連接數目:" - -#: plugins/Scheduler/plugin.py:120 -msgid "Scheduler Settings" -msgstr "排程器設定" - -#: plugins/Scheduler/plugin.py:179 -msgid "Green is the high limits, yellow is the low limits and red is stopped" -msgstr "綠色代表此時段採用速度上限、黃色代表採用速度下限、紅色代表不設限" - -#: plugins/Scheduler/plugin.py:180 -msgid "If a limit is set to -1, it is unlimitted." -msgstr "如果速限設為 -1 代表不設限。" - -#: plugins/WebUi/__init__.py:194 -msgid "WebUi Config" -msgstr "WebUi 設定" - -#: plugins/WebUi/__init__.py:202 -msgid "Port Number" -msgstr "通訊埠" - -#: plugins/WebUi/__init__.py:203 -msgid "New Password" -msgstr "新密碼" - -#: plugins/WebUi/__init__.py:204 -msgid "New Password(confirm)" -msgstr "新密碼 (再次確認)" - -#: plugins/WebUi/__init__.py:205 -msgid "Template" -msgstr "樣板" - -#: plugins/WebUi/__init__.py:206 -msgid "Button Style" -msgstr "按鈕樣式" - -#: plugins/WebUi/__init__.py:208 -msgid "Cache Templates" -msgstr "快取樣板" - -#: plugins/WebUi/__init__.py:210 -msgid "https://" -msgstr "https://" - -#: plugins/WebUi/__init__.py:227 -msgid "Text and image" -msgstr "文字及圖片" - -#: plugins/WebUi/__init__.py:227 -msgid "Image Only" -msgstr "只顯示圖片" - -#: plugins/WebUi/__init__.py:227 -msgid "Text Only" -msgstr "只顯示文字" - -#: plugins/WebUi/__init__.py:262 -msgid "Confirmed Password <> New Password\n" -msgstr "已確認密碼 <> 新密碼\n" - -#: plugins/WebUi/webserver_common.py:62 -msgid "translate something" -msgstr "翻譯成別種語言" - -#: plugins/WebUi/deluge_webserver.py:193 -msgid "Choose an url or a torrent, not both." -msgstr "請選擇網址或種子,不要同時選擇" - -#: plugins/WebUi/deluge_webserver.py:203 -msgid "no data." -msgstr "無資料" - -#: plugins/WebUi/deluge_webserver.py:304 -msgid "refresh must be > 0" -msgstr "更新頻率要大於 0" - -#: plugins/WebUi/scripts/template_strings.py:1 -msgid "# Of Files" -msgstr "檔案總數" - -#: plugins/WebUi/scripts/template_strings.py:2 -msgid "About" -msgstr "關於" - -#: plugins/WebUi/scripts/template_strings.py:5 -msgid "Add torrent" -msgstr "新增種子" - -#: plugins/WebUi/scripts/template_strings.py:6 -msgid "Apply" -msgstr "套用" - -#: plugins/WebUi/scripts/template_strings.py:7 -msgid "Auto refresh:" -msgstr "自動更新間隔:" - -#: plugins/WebUi/scripts/template_strings.py:8 -msgid "Ava" -msgstr "可得性" - -#: plugins/WebUi/scripts/template_strings.py:10 -msgid "Config" -msgstr "設定" - -#: plugins/WebUi/scripts/template_strings.py:12 -msgid "Debug:Data Dump" -msgstr "除錯: 資料傾印" - -#: plugins/WebUi/scripts/template_strings.py:14 -msgid "Delete downloaded files." -msgstr "刪除已下載檔案" - -#: plugins/WebUi/scripts/template_strings.py:16 -msgid "Disable" -msgstr "停用" - -#: plugins/WebUi/scripts/template_strings.py:20 -msgid "Downloaded" -msgstr "已下載" - -#: plugins/WebUi/scripts/template_strings.py:22 -msgid "Enable" -msgstr "啟用" - -#: plugins/WebUi/scripts/template_strings.py:23 -msgid "Error" -msgstr "錯誤" - -#: plugins/WebUi/scripts/template_strings.py:24 -msgid "Eta" -msgstr "完成時間" - -#: plugins/WebUi/scripts/template_strings.py:25 -msgid "Login" -msgstr "登入" - -#: plugins/WebUi/scripts/template_strings.py:26 -msgid "Logout" -msgstr "登出" - -#: plugins/WebUi/scripts/template_strings.py:28 -msgid "Next Announce" -msgstr "下次通告時間" - -#: plugins/WebUi/scripts/template_strings.py:29 -msgid "Off" -msgstr "關閉" - -#: plugins/WebUi/scripts/template_strings.py:31 -msgid "Password is invalid,try again" -msgstr "密碼無效,請再試一次" - -#: plugins/WebUi/scripts/template_strings.py:33 -msgid "Pause all" -msgstr "全部暫停" - -#: plugins/WebUi/scripts/template_strings.py:35 -msgid "Pieces" -msgstr "片段" - -#: plugins/WebUi/scripts/template_strings.py:37 -msgid "Queue Down" -msgstr "往下移" - -#: plugins/WebUi/scripts/template_strings.py:38 -msgid "Queue Position" -msgstr "佇列位置" - -#: plugins/WebUi/scripts/template_strings.py:39 -msgid "Queue Up" -msgstr "往上移" - -#: plugins/WebUi/scripts/template_strings.py:41 -msgid "Reannounce" -msgstr "重新通告" - -#: plugins/WebUi/scripts/template_strings.py:42 -msgid "Refresh page every:" -msgstr "更新頁面頻率:" - -#: plugins/WebUi/scripts/template_strings.py:44 -msgid "Remove torrent" -msgstr "移除種子" - -#: plugins/WebUi/scripts/template_strings.py:46 -msgid "Resume all" -msgstr "全部續傳" - -#: plugins/WebUi/scripts/template_strings.py:48 -msgid "Set" -msgstr "設定" - -#: plugins/WebUi/scripts/template_strings.py:49 -msgid "Set Timeout" -msgstr "設定逾時時間" - -#: plugins/WebUi/scripts/template_strings.py:52 -msgid "Speed" -msgstr "速度" - -#: plugins/WebUi/scripts/template_strings.py:53 -msgid "Start" -msgstr "開始" - -#: plugins/WebUi/scripts/template_strings.py:54 -msgid "Submit" -msgstr "送出" - -#: plugins/WebUi/scripts/template_strings.py:55 -msgid "Torrent list" -msgstr "種子清單" - -#: plugins/WebUi/scripts/template_strings.py:56 -msgid "Total Size" -msgstr "總大小" - -#: plugins/WebUi/scripts/template_strings.py:57 -msgid "Tracker" -msgstr "伺服器" - -#: plugins/WebUi/scripts/template_strings.py:58 -msgid "Tracker Status" -msgstr "伺服器狀態" - -#: plugins/WebUi/scripts/template_strings.py:62 -msgid "Upload torrent" -msgstr "上傳種子" - -#: plugins/WebUi/scripts/template_strings.py:63 -msgid "Uploaded" -msgstr "已上傳" - -#: plugins/WebUi/scripts/template_strings.py:64 -msgid "Url" -msgstr "網址" - -#: plugins/WebUi/scripts/template_strings.py:65 -msgid "seconds" -msgstr "秒" - -#: plugins/FlexRSS/FlexRSS.glade:6 -msgid "FlexRSS" -msgstr "FlexRSS" - -#: plugins/FlexRSS/FlexRSS.glade:103 -msgid "Feed will be retrieved automatically, based on the update interval." -msgstr "自動依設定好的更新頻率取回消息來源" - -#: plugins/FlexRSS/FlexRSS.glade:115 -msgid "Feed must be refreshed manually." -msgstr "消息來源必須手動更新" - -#: plugins/FlexRSS/FlexRSS.glade:116 -msgid "Disabled" -msgstr "已停用" - -#: plugins/FlexRSS/FlexRSS.glade:151 -msgid "Update Interval" -msgstr "更新頻率" - -#: plugins/FlexRSS/FlexRSS.glade:165 -msgid "URL" -msgstr "網址" - -#: plugins/FlexRSS/FlexRSS.glade:192 -msgid "900" -msgstr "900" - -#: plugins/FlexRSS/FlexRSS.glade:240 -msgid "Feeds" -msgstr "消息來源" - -#: plugins/FlexRSS/FlexRSS.glade:384 -msgid "Type" -msgstr "類型" - -#: plugins/FlexRSS/FlexRSS.glade:397 -msgid "Feed" -msgstr "消息來源" - -#: plugins/FlexRSS/FlexRSS.glade:439 -msgid "Information" -msgstr "資訊" - -#: plugins/FlexRSS/FlexRSS.glade:511 -msgid "Patterns" -msgstr "比對樣式" - -#: plugins/FlexRSS/FlexRSS.glade:549 plugins/FlexRSS/FlexRSS.glade:724 -msgid "From" -msgstr "開始於" - -#: plugins/FlexRSS/FlexRSS.glade:565 plugins/FlexRSS/FlexRSS.glade:641 -#: plugins/FlexRSS/FlexRSS.glade:826 -msgid "Season" -msgstr "第幾季" - -#: plugins/FlexRSS/FlexRSS.glade:594 plugins/FlexRSS/FlexRSS.glade:675 -#: plugins/FlexRSS/FlexRSS.glade:833 -msgid "Episode" -msgstr "第幾集" - -#: plugins/FlexRSS/FlexRSS.glade:623 plugins/FlexRSS/FlexRSS.glade:740 -msgid "Thru" -msgstr "結束於" - -#: plugins/FlexRSS/FlexRSS.glade:766 -msgid "History Restriction" -msgstr "設定不下載的集數" - -#: plugins/FlexRSS/FlexRSS.glade:810 -msgid "Doesn't Match" -msgstr "不符合" - -#: plugins/FlexRSS/FlexRSS.glade:875 -msgid "Year" -msgstr "年" - -#: plugins/FlexRSS/FlexRSS.glade:882 -msgid "Month" -msgstr "月" - -#: plugins/FlexRSS/FlexRSS.glade:893 -msgid "Day" -msgstr "日" - -#: plugins/FlexRSS/FlexRSS.glade:960 -msgid "Test" -msgstr "測試" - -#: plugins/FlexRSS/FlexRSS.glade:992 -msgid "Insert torrent at top of queue." -msgstr "將種子放到佇列最頂端" - -#: plugins/FlexRSS/FlexRSS.glade:1002 -msgid "Set state to paused." -msgstr "取回種子後設為暫停狀態" - -#: plugins/FlexRSS/FlexRSS.glade:1015 -msgid "Delete filter when matched." -msgstr "找到相符的種子後刪除此條件" - -#: plugins/FlexRSS/FlexRSS.glade:1031 -msgid "Download" -msgstr "下載" - -#: plugins/FlexRSS/FlexRSS.glade:1084 -msgid "Replacement" -msgstr "取代為" - -#: plugins/FlexRSS/FlexRSS.glade:1098 -msgid "Pattern" -msgstr "比對樣式" - -#: plugins/FlexRSS/FlexRSS.glade:1111 -msgid "Link Rewriting" -msgstr "鏈結重新導向" - -#: plugins/FlexRSS/FlexRSS.glade:1143 -msgid "" -"Content will be saved to Deluge's default directory, or a prompt will appear " -"if none is set." -msgstr "取回的內容會被存在 Deluge 的預設目錄,若未設定則提示要存到何處。" - -#: plugins/FlexRSS/FlexRSS.glade:1144 -msgid "Deluge default" -msgstr "Deluge 預設目錄" - -#: plugins/FlexRSS/FlexRSS.glade:1159 -msgid "Content will be automatically downloaded to the specified directory." -msgstr "取回的內容會自動存到你指定的目錄。" - -#: plugins/FlexRSS/FlexRSS.glade:1160 -msgid "Choose:" -msgstr "請選擇:" - -#: plugins/FlexRSS/FlexRSS.glade:1190 -msgid "Output" -msgstr "輸出目錄" - -#: plugins/FlexRSS/FlexRSS.glade:1251 -msgid "Filters" -msgstr "過濾條件" - -#: plugins/FlexRSS/FlexRSS.glade:1282 -msgid "Show a FlexRSS icon in Deluge's toolbar." -msgstr "於 Deluge 工具列上顯示 FlexRSS 圖示。" - -#: plugins/FlexRSS/FlexRSS.glade:1283 -msgid "Show button on toolbar." -msgstr "於工具列顯示圖示" - -#: plugins/FlexRSS/FlexRSS.glade:1300 -msgid "Interface" -msgstr "介面" - -#: plugins/FlexRSS/FlexRSS.glade:1331 -msgid "" -"Feeds will be retrieved and parsed in their own threads. The application " -"will not be blocked, but it can be unreliable." -msgstr "用不同的執行緒分別取回及解析消息來源 (Feed)。選用這個選項不會讓程式當掉,但會變得很不穩定。" - -#: plugins/FlexRSS/FlexRSS.glade:1332 -msgid "Threaded (experimental)" -msgstr "多執行緒模式 (尚在測試中)" - -#: plugins/FlexRSS/FlexRSS.glade:1346 -msgid "Feed Retrieval" -msgstr "消息來源取回" - -#: plugins/FlexRSS/FlexRSS.glade:1451 -msgid "Domain" -msgstr "網域" - -#: plugins/FlexRSS/FlexRSS.glade:1462 -msgid "Path" -msgstr "路徑" - -#: plugins/FlexRSS/FlexRSS.glade:1488 -msgid "Value" -msgstr "值" - -#: plugins/FlexRSS/FlexRSS.glade:1561 -msgid "Cookies" -msgstr "Cookies" - -#: plugins/FlexRSS/FlexRSS.glade:1582 -msgid "Configuration" -msgstr "組態設定" - -#: plugins/Search/searchdlg.glade:7 -msgid "Manage Search Plugins" -msgstr "管理搜尋模組" - -#: plugins/Search/searchdlg.glade:79 -msgid "Name:" -msgstr "名稱:" - -#: plugins/Search/searchdlg.glade:123 -msgid "" -"Add a new search engine by entering a Name and a URL. For Name, enter the " -"name of the search engine to be used. For URL, enter the url of the seach " -"page. The user's search query will replace any instance of ${query} in the " -"URL.\n" -"For example, a Google search would be:\n" -"Name: Google\n" -"URL: http://www.google.com/search?q=${query}" -msgstr "" -"輸入名稱和網址新增搜尋引擎。名稱即該搜尋引擎要用的名稱、網址則是搜尋頁面的網址。網址中的 ${query} 會被替換為使用者搜尋的字串。\n" -"例如,Google 搜尋要設為:\n" -"名稱: Google\n" -"網址: http://www.google.com/search?q=${query}" - -#: plugins/Search/searchdlg.glade:133 -msgid "Help" -msgstr "說明" - -#: plugins/Search/__init__.py:37 -#, fuzzy -msgid "Search for torrents anonymously" -msgstr "匿名搜尋torrents" - -#: plugins/Search/__init__.py:80 -msgid "Search String" -msgstr "搜尋字串" - -#: plugins/Search/__init__.py:101 plugins/Search/__init__.py:184 -msgid "Choose an Engine" -msgstr "選擇搜尋" - -#: plugins/Search/__init__.py:105 -msgid "Manage Engines" -msgstr "管理搜尋引擎" - -#: plugins/Search/__init__.py:205 -msgid "Search " -msgstr "搜尋 " diff --git a/scripts/deluge b/scripts/deluge deleted file mode 100755 index c2e643bd8..000000000 --- a/scripts/deluge +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/env python -# -# deluge -# Copyright (C) Zach Tibbitts 2006 -# Copyright (C) Alon Zakai 2006 -# -# -# -# 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 2 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 os -from optparse import OptionParser -import re -import subprocess -import sys - -import deluge -import deluge.common -import deluge.core -import deluge._dbus as dbus -import deluge.interface - -parser = OptionParser(usage="%prog [options] [torrents to add]", - version=deluge.common.PROGRAM_VERSION) -parser.add_option("-c", "--config", dest="config", help="Sets the configuration path") -(options, args) = parser.parse_args() - -if (options.config != None): - deluge.common.CONFIG_DIR = options.config - -if hasattr(sys, "frozen"): - sys.stdout = open(os.path.join(deluge.common.CONFIG_DIR,"deluge.stdout.log"), "w") - sys.stderr = open(os.path.join(deluge.common.CONFIG_DIR,"deluge.stderr.log"), "w") - -def upgrade_old_persistent_state(): - pstate_file_path = os.path.join(deluge.common.CONFIG_DIR, - deluge.core.STATE_FILENAME) - ## The persistent_state object moved from the deluge.deluge module to the - ## deluge.core module from 0.5; so let's edit the user's saved data to - ## reflect this. - if os.path.isfile(pstate_file_path): - try: - pstate_fd = open(pstate_file_path, "r") - pstate_data = pstate_fd.read() - pstate_fd.close() - - ## If the file was empty, then we should remove it so that the - ## pickler doesn't not attempt to unpack an empty state. - if len(pstate_data) is 0: - os.remove(pstate_file_path) - print "Empty persistent state data file removed successfully." - ## The file exists and contains data, so let's do a regex-based - ## find/replace to update the module name. - else: - pstate_old_regex = re.compile("\(ideluge\.deluge$", - re.MULTILINE) - if re.search(pstate_old_regex, pstate_data): - pstate_new_data = re.sub(pstate_old_regex, - "(ideluge.core", pstate_data) - pstate_fd = open(pstate_file_path, "w") - pstate_fd.write(pstate_new_data) - pstate_fd.close() - print "Persistent state data updated successfully." - except OSError, oopsie: - print >> sys.stderr, \ -"""There was an error updating the persistent.state file. -If this is an upgrade from an earlier version of Deluge, this may cause bugs -or failures in startup. You may wish to remove it manually. (%s) -Continuing...""" % pstate_file_path - print >> sys.stderr, "The error was: %s." % oopsie - -def get_cmd_line_torrents(): - cmd_line_torrents = [] - for torrent in args: - if deluge.common.is_url(torrent): - filename = deluge.common.fetch_url(torrent) - if filename: - cmd_line_torrents.append(filename) - else: - if not torrent.endswith(".torrent"): - print "Error,", torrent, " does not seem to be a .torrent file" - else: - cmd_line_torrents.append(os.path.abspath(torrent)) - return cmd_line_torrents - -def start_deluge(): - print "Starting new Deluge session..." - upgrade_old_persistent_state() - interface = deluge.interface.DelugeGTK(config_dir=deluge.common.CONFIG_DIR) - interface.start(get_cmd_line_torrents()) - -try: - bus = dbus.SessionBus() -except: - if not deluge.common.windows_check(): - subprocess.Popen(["dbus-launch", "deluge"] + sys.argv[1:]) -else: - dbus_objects = dbus.Interface(bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus'), 'org.freedesktop.DBus').ListNames() - - if not "org.deluge_torrent.Deluge" in dbus_objects: - print "no existing Deluge session" - if not os.path.exists(os.path.join(deluge.common.CONFIG_DIR, 'firstrun')): - import deluge.wizard - deluge.wizard.WizardGTK() - - start_deluge() - - else: - ## This connects to the deluge interface - print "create proxy object" - proxy = bus.get_object('org.deluge_torrent.Deluge', '/org/deluge_torrent/DelugeObject') - print "create iface" - deluge_iface = dbus.Interface(proxy, 'org.deluge_torrent.Deluge') - print "send to iface" - - for filename in get_cmd_line_torrents(): - deluge_iface.interactive_add_torrent(filename) diff --git a/setup.py b/setup.py index 15ae84472..db9cf8be8 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,6 @@ -# Copyright (c) 2006 Zach Tibbitts ('zachtib') +# setup.py +# +# Copyright (C) 2007 Andrew Resch ('andar') # # 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 @@ -7,283 +9,208 @@ # # 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 +# 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. +# 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. +# 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. -NAME = "deluge" -FULLNAME = "Deluge BitTorrent Client" -VERSION = "0.5.9.3" -AUTHOR = "Zach Tibbitts, Alon Zakai, Marcos Pinto, Andrew Resch, Alex Dedul" -EMAIL = "zach@collegegeek.org, kripkensteiner@gmail.com, marcospinto@dipconsultants.com, alonzakai@gmail.com, rotmer@gmail.com" -DESCRIPTION = "A GTK BitTorrent client written in Python and C++" -URL = "http://deluge-torrent.org" -LICENSE = "GPLv2" +import ez_setup +ez_setup.use_setuptools() +import glob -import os, platform -print "Attempting to detect your system information" -if platform.machine() == "i386" or platform.machine() == "i686": - print "32bit x86 system detected" - ARCH = "x86" -elif platform.machine() == "x86_64" or platform.machine() == "amd64": - print "64bit x86_64 system detected" - ARCH = "x64" -elif platform.machine() == "Power Macintosh": - print "PowerPC system detected" - ARCH = "ppc" -else: - print "Couldn't detect CPU architecture" - ARCH = "" -if platform.system() == "Linux": - print "Linux operating system detected" - OS = "linux" -elif platform.system() == "Darwin" : - print "Darwin / OS X system detected" - OS = "osx" -elif platform.system() == "FreeBSD" : - print "FreeBSD operating system detected" - OS = "freebsd" -elif platform.system() in ('Windows', 'Microsoft'): - print "Windows system detected" - OS = "win" -elif os.name == "posix": - print "Unix system detected" - OS = "nix" -else: - print "Couldn't detect operating system" - OS = "" -import os.path, glob -from distutils.core import setup, Extension -from distutils import sysconfig -import shutil -from distutils import cmd +from setuptools import setup, find_packages, Extension +from distutils import cmd, sysconfig +from distutils.command.build import build as _build from distutils.command.install import install as _install from distutils.command.install_data import install_data as _install_data -from distutils.command.build import build as _build -if OS == "win": - from distutils.command.build_ext import build_ext as _build_ext + import msgfmt +import os +import platform python_version = platform.python_version()[0:3] - -# NOTE: The following "hack" removes the -g and -Wstrict-prototypes -# build options from the command that will compile the C++ module, -# deluge_core. While we understand that you aren't generally -# encouraged to do this, we have done so for the following reasons: -# 1) The -g compiler option produces debugging information about -# the compiled module. However, this option increases the -# size of deluge_core.so from ~1.9MB to 13.6MB and slows down -# the program's execution without offering any benefits -# whatsoever. -# 2) -Wstrict-prototypes is not a valid C++ build option, and the -# compiler will throw a number of warnings at compile time. -# While this does not really impact anything, it makes it -# seem as if something is going wrong with the compile, and -# it has been removed to prevent confusion. - -if not OS == "win": - EXTRA_COMPILE_ARGS = ["-Wno-missing-braces", - "-DHAVE_INCLUDE_LIBTORRENT_ASIO____ASIO_HPP=1", - "-DHAVE_INCLUDE_LIBTORRENT_ASIO_SSL_STREAM_HPP=1", - "-DHAVE_INCLUDE_LIBTORRENT_ASIO_IP_TCP_HPP=1", - "-DHAVE_PTHREAD=1", "-DTORRENT_USE_OPENSSL=1", "-DHAVE_SSL=1", - "-DNDEBUG=1", "-O2"] - if ARCH == "x64": - EXTRA_COMPILE_ARGS.append("-DAMD64") - - includedirs = ['./libtorrent', './libtorrent/include', - './libtorrent/include/libtorrent', - '/usr/include/python' + python_version] - - if OS == "linux": - if os.path.exists(os.path.join(sysconfig.get_config_vars()['LIBDIR'], \ - 'libboost_filesystem-mt.so')): - boost_filesystem = "boost_filesystem-mt" - elif os.path.exists(os.path.join(sysconfig.get_config_vars()['LIBDIR'], \ - 'libboost_filesystem.so')): - boost_filesystem = "boost_filesystem" - if os.path.exists(os.path.join(sysconfig.get_config_vars()['LIBDIR'], \ - 'libboost_date_time-mt.so')): - boost_date_time = "boost_date_time-mt" - elif os.path.exists(os.path.join(sysconfig.get_config_vars()['LIBDIR'], \ - 'libboost_date_time.so')): - boost_date_time = "boost_date_time" - if os.path.exists(os.path.join(sysconfig.get_config_vars()['LIBDIR'], \ - 'libboost_thread-mt.so')): - boost_thread = "boost_thread-mt" - elif os.path.exists(os.path.join(sysconfig.get_config_vars()['LIBDIR'], \ - 'libboost_thread.so')): - boost_thread = "boost_thread" - - if 'boost_filesystem' not in vars(): - boost_filesystem = "boost_filesystem-mt" - if 'boost_date_time' not in vars(): - boost_date_time = "boost_date_time-mt" - if 'boost_thread' not in vars(): - boost_thread = "boost_thread-mt" - - elif OS == "freebsd": - boost_filesystem = "boost_filesystem" - boost_date_time = "boost_date_time" - boost_thread = "boost_thread" +def windows_check(): + import platform + if platform.system() in ('Windows', 'Microsoft'): + return True else: - boost_filesystem = "boost_filesystem-mt" - boost_date_time = "boost_date_time-mt" - boost_thread = "boost_thread-mt" + return False - librariestype = [boost_filesystem, boost_date_time, - boost_thread, 'z', 'pthread', 'ssl', 'crypto'] +# Try to get SVN revision number to append to version +revision_string = "" +try: + stdout = os.popen("svn info") + for line in stdout: + if line.split(" ")[0] == "Revision:": + revision_string = line.split(" ")[1].strip() + break + # Try to get the SVN revision on Gentoo systems + if revision_string == "": + stdout = os.popen("svn info /usr/portage/distfiles/svn-src/deluge/deluge-0.6") + for line in stdout: + if line.split(" ")[0] == "Revision:": + revision_string = line.split(" ")[1].strip() + break + + f = open("deluge/data/revision", "w") + f.write(revision_string) + f.close() +except: + pass - if os == "linux": - librariestype += ['rt'] + +if not os.environ.has_key("CC"): + os.environ["CC"] = "gcc" + +if not os.environ.has_key("CXX"): + os.environ["CXX"] = "gcc" - removals = ['-g', '-Wstrict-prototypes'] +if not os.environ.has_key("CPP"): + os.environ["CPP"] = "g++" + +# The libtorrent extension +_extra_compile_args = [ + "-D_FILE_OFFSET_BITS=64", + "-DNDEBUG", + "-DTORRENT_USE_OPENSSL=1", + "-O2", + ] +if windows_check(): + _extra_compile_args += [ + "-D__USE_W32_SOCKETS", + "-D_WIN32_WINNT=0x0500", + "-D_WIN32", + "-DWIN32_LEAN_AND_MEAN", + "-DBOOST_ALL_NO_LIB", + "-DBOOST_STATIC_LINK", + "-DBOOST_THREAD_USE_LIB", + "-DBOOST_WINDOWS", + "-DBOOST_WINDOWS_API", + "-DTORRENT_BUILDING_SHARED", + "-DTORRENT_LINKING_SHARED", + "-DWIN32", + "-DUNICODE", + "-D_UNICODE", + "/GR", + "/Zc:wchar_t", + ] +else: + _extra_compile_args += ["-Wno-missing-braces"] + +removals = ["-Wstrict-prototypes"] + +if not windows_check(): if python_version == '2.5': cv_opt = sysconfig.get_config_vars()["CFLAGS"] for removal in removals: cv_opt = cv_opt.replace(removal, " ") - sysconfig.get_config_vars()["CFLAGS"] = ' '.join(cv_opt.split()) + sysconfig.get_config_vars()["CFLAGS"] = " ".join(cv_opt.split()) else: cv_opt = sysconfig.get_config_vars()["OPT"] for removal in removals: cv_opt = cv_opt.replace(removal, " ") - sysconfig.get_config_vars()["OPT"] = ' '.join(cv_opt.split()) + sysconfig.get_config_vars()["OPT"] = " ".join(cv_opt.split()) + +_library_dirs = [ +] + +_include_dirs = [ + './libtorrent', + './libtorrent/include', + './libtorrent/include/libtorrent', +] + +if windows_check(): + _include_dirs += ['./win32/include','./win32/include/openssl', './win32/include/zlib'] + _library_dirs += ['./win32/lib'] + _libraries = [ + 'advapi32', + 'boost_filesystem-vc71-mt-1_35', + 'boost_date_time-vc71-mt-1_35', + 'boost_iostreams-vc71-mt-1_35', + 'boost_python-vc71-mt-1_35', + 'boost_system-vc71-mt-1_35', + 'boost_thread-vc71-mt-1_35', + 'gdi32', + 'libeay32', + 'ssleay32', + 'ws2_32', + 'wsock32', + 'zlib' + ] else: - EXTRA_COMPILE_ARGS = [ '-O2', '-DBOOST_WINDOWS', - '-fno-strict-aliasing', - '-Wno-missing-braces', - '-DWIN32_LEAN_AND_MEAN', - '-D_WIN32_WINNT=0x0500', - '-D__USE_W32_SOCKETS', - '-D_WIN32', - '-DWIN32', - '-DUNICODE', - '-DBOOST_ALL_NO_LIB', - '-D_FILE_OFFSET_BITS=64', - '-DBOOST_THREAD_USE_LIB', - '-DTORRENT_BUILDING_SHARED', - '-DTORRENT_LINKING_SHARED', - '-DTORRENT_USE_OPENSSL=1', - '-DNDEBUG=1'] - - EXTRA_LINK_ARGS = ['-L.\win32\lib'] - includedirs = ['./libtorrent', './libtorrent/include', './libtorrent/include/libtorrent', './win32/include'] - librariestype = ['boost_filesystem', 'boost_date_time', - 'boost_thread', 'z', 'ssl' ,'wsock32' ,'crypto' ,'gdi32' ,'ws2_32'] - -# NOTE: The Rasterbar Libtorrent source code is in the libtorrent/ directory -# inside of Deluge's source tarball. - -def fetchCpp(): - for root,dirs,files in os.walk('libtorrent'): - if '.svn' in dirs: - dirs.remove('.svn') - for file in files: - if file.endswith('.cpp'): - yield os.path.join(root,file) - -sources=list(fetchCpp()) -sources.append(os.path.join('src','deluge_core.cpp')) -if not OS == "win": - sources.remove('libtorrent/src/file_win.cpp') - deluge_core = Extension('deluge_core', - include_dirs = includedirs, - libraries = librariestype, - extra_compile_args = EXTRA_COMPILE_ARGS, - sources = sources) -else: - sources.remove('libtorrent\\src\\file.cpp') - deluge_core = Extension('deluge_core', - include_dirs = includedirs, - libraries = librariestype, - extra_compile_args = EXTRA_COMPILE_ARGS, - extra_link_args = EXTRA_LINK_ARGS, - sources = sources) - -# Thanks to Iain Nicol for code to save the location for installed prefix -# At runtime, we need to know where we installed the data to. - -class write_data_install_path(cmd.Command): - description = 'saves the data installation path for access at runtime' + _include_dirs += ['/usr/include/python' + python_version] + _libraries = [ + 'boost_filesystem', + 'boost_date_time', + 'boost_iostreams', + 'boost_python', + 'boost_thread', + 'pthread', + 'ssl', + 'z' + ] - def initialize_options(self): - self.prefix = None - self.lib_build_dir = None +_sources = glob.glob("./libtorrent/src/*.cpp") + \ + glob.glob("./libtorrent/src/*.c") + \ + glob.glob("./libtorrent/src/kademlia/*.cpp") + \ + glob.glob("./libtorrent/bindings/python/src/*.cpp") - def finalize_options(self): - self.set_undefined_options('install', - ('prefix', 'prefix') - ) - self.set_undefined_options('build', - ('build_lib', 'lib_build_dir') - ) +# Remove file_win.cpp if not on windows +if windows_check(): + for source in _sources: + if "file.cpp" in source: + _sources.remove(source) + break +else: + for source in _sources: + if "file_win.cpp" in source: + _sources.remove(source) + break - def run(self): - conf_filename = os.path.join(self.lib_build_dir, - 'deluge', 'common.py') - - conf_file = open(conf_filename, 'r') - data = conf_file.read() - conf_file.close() - data = data.replace('@datadir@', self.prefix) - conf_file = open(conf_filename, 'w') - conf_file.write(data) - conf_file.close() - - def get_outputs(self): return [] - -class unwrite_data_install_path(cmd.Command): - description = 'undoes write_data_install_path' - - def initialize_options(self): - self.lib_build_dir = None - - def finalize_options(self): - self.set_undefined_options('build', - ('build_lib', 'lib_build_dir') - ) - - def run(self): - dest = os.path.join(self.lib_build_dir, - 'deluge', 'common.py') - shutil.copyfile('src/common.py', dest) - - def get_outputs(self): return [] +libtorrent = Extension( + 'libtorrent', + extra_compile_args = _extra_compile_args, + include_dirs = _include_dirs, + libraries = _libraries, + library_dirs = _library_dirs, + sources = _sources +) class build_trans(cmd.Command): description = 'Compile .po files into .mo files' - + def initialize_options(self): pass - def finalize_options(self): + def finalize_options(self): pass def run(self): - po_dir = os.path.join(os.path.dirname(os.curdir), 'po') + po_dir = os.path.join(os.path.dirname(__file__), 'deluge/i18n/') for path, names, filenames in os.walk(po_dir): for f in filenames: if f.endswith('.po'): lang = f[:len(f) - 3] src = os.path.join(path, f) - dest_path = os.path.join('build', 'locale', lang, 'LC_MESSAGES') + dest_path = os.path.join('deluge', 'i18n', lang, \ + 'LC_MESSAGES') dest = os.path.join(dest_path, 'deluge.mo') if not os.path.exists(dest_path): os.makedirs(dest_path) @@ -302,101 +229,107 @@ class build(_build): def run(self): _build.run(self) -class install(_install): - sub_commands = [('write_data_install_path', None)] + \ - _install.sub_commands + [('unwrite_data_install_path', None)] - def run(self): - _install.run(self) - class install_data(_install_data): def run(self): - for lang in os.listdir('build/locale/'): - lang_dir = os.path.join('share', 'locale', lang, 'LC_MESSAGES') - lang_file = os.path.join('build', 'locale', lang, 'LC_MESSAGES', 'deluge.mo') - self.data_files.append( (lang_dir, [lang_file]) ) _install_data.run(self) -if OS == "win": - class build_ext(_build_ext): - def build_extensions(self): - # Linking against this library causes deluge_core.pyd to crash - # on Python >= 2.4. Maybe related to strdup calls, cfr. - # http://mail.python.org/pipermail/distutils-sig/2005-April/004433.html - if 'msvcr71' in self.compiler.dll_libraries: - self.compiler.dll_libraries.remove('msvcr71') - _build_ext.build_extensions(self) -if not OS == "win": - cmdclass = { - 'build': build, - 'install': install, - 'build_trans': build_trans, - 'install_data': install_data, - 'write_data_install_path': write_data_install_path, - 'unwrite_data_install_path': unwrite_data_install_path, - } -else: - cmdclass = { - 'build': build, - 'build_ext' : build_ext, - 'install': install, - 'build_trans': build_trans, - 'install_data': install_data, - 'write_data_install_path': write_data_install_path, - 'unwrite_data_install_path': unwrite_data_install_path, - } +cmdclass = { + 'build': build, + 'build_trans': build_trans, + 'install_data': install_data +} +# Build the plugin eggs +PLUGIN_PATH = "deluge/plugins/*" +if windows_check(): + PLUGIN_PATH = "deluge\\plugins\\" + +for path in glob.glob(PLUGIN_PATH): + if os.path.exists(os.path.join(path, "setup.py")): + os.system("cd " + path + "&& python setup.py bdist_egg -d ..") -data = [('share/deluge/glade', glob.glob('glade/*.glade')), - ('share/deluge/pixmaps', glob.glob('pixmaps/*.png')), - ('share/deluge/pixmaps', glob.glob('pixmaps/*.svg')), - ('share/deluge/icons/scalable/apps', glob.glob('icons/scalable/apps/*.svg')), - ('share/deluge/icons/hicolor', glob.glob('icons/hicolor/*.png')), - ('share/icons/hicolor/128x128', glob.glob('icons/hicolor/128x128/*.png')), - ('share/icons/hicolor/128x128/apps', glob.glob('icons/hicolor/128x128/apps/*.png')), - ('share/icons/hicolor/16x16', glob.glob('icons/hicolor/16x16/*.png')), - ('share/icons/hicolor/16x16/apps', glob.glob('icons/hicolor/16x16/apps/*.png')), - ('share/icons/hicolor/192x192', glob.glob('icons/hicolor/192x192/*.png')), - ('share/icons/hicolor/192x192/apps', glob.glob('icons/hicolor/192x192/apps/*.png')), - ('share/icons/hicolor/22x22', glob.glob('icons/hicolor/22x22/*.png')), - ('share/icons/hicolor/22x22/apps', glob.glob('icons/hicolor/22x22/apps/*.png')), - ('share/icons/hicolor/24x24', glob.glob('icons/hicolor/24x24/*.png')), - ('share/icons/hicolor/24x24/apps', glob.glob('icons/hicolor/24x24/apps/*.png')), - ('share/icons/hicolor/256x256', glob.glob('icons/hicolor/256x256/*.png')), - ('share/icons/hicolor/256x256/apps', glob.glob('icons/hicolor/256x256/apps/*.png')), - ('share/icons/hicolor/32x32', glob.glob('icons/hicolor/32x32/*.png')), - ('share/icons/hicolor/32x32/apps', glob.glob('icons/hicolor/32x32/apps/*.png')), - ('share/icons/hicolor/36x36', glob.glob('icons/hicolor/36x36/*.png')), - ('share/icons/hicolor/36x36/apps', glob.glob('icons/hicolor/36x36/apps/*.png')), - ('share/icons/hicolor/48x48', glob.glob('icons/hicolor/48x48/*.png')), - ('share/icons/hicolor/48x48/apps', glob.glob('icons/hicolor/48x48/apps/*.png')), - ('share/icons/hicolor/64x64', glob.glob('icons/hicolor/64x64/*.png')), - ('share/icons/hicolor/64x64/apps', glob.glob('icons/hicolor/64x64/apps/*.png')), - ('share/icons/hicolor/72x72', glob.glob('icons/hicolor/72x72/*.png')), - ('share/icons/hicolor/72x72/apps', glob.glob('icons/hicolor/72x72/apps/*.png')), - ('share/icons/hicolor/96x96', glob.glob('icons/hicolor/96x96/*.png')), - ('share/icons/hicolor/96x96/apps', glob.glob('icons/hicolor/96x96/apps/*.png')), - ('share/deluge/pixmaps/flags18x12', glob.glob('pixmaps/flags18x12/*.png')), - ('share/deluge/pixmaps/flags25x15', glob.glob('pixmaps/flags25x15/*.png')), - ('share/applications' , ['deluge.desktop']), - ('share/pixmaps' , ['deluge.png'])] - -# New code to glob plugins and include subdirs: -for o in os.walk('plugins'): - path = o[0] - if not path.count('/.') and not path.count('\\.'): - items = o[2] - for x in range(len(items)): - items[x] = path + '/' + items[x] - data.append( ('share/deluge/' + path, items)) - -setup(name=NAME, fullname=FULLNAME, version=VERSION, - author=AUTHOR, author_email=EMAIL, description=DESCRIPTION, - url=URL, license=LICENSE, - scripts=["scripts/deluge"], - packages=['deluge'], - package_dir = {'deluge': 'src'}, - data_files=data, - ext_package='deluge', - ext_modules=[deluge_core], - cmdclass=cmdclass +# Main setup +PREFIX = "/usr/" +if windows_check(): + PREFIX = "" +_data_files = [(os.path.join(PREFIX, 'share/icons/scalable/apps'), [ + 'deluge/data/icons/scalable/apps/deluge.svg']), + (os.path.join(PREFIX, 'share/icons/hicolor/128x128/apps'), [ + 'deluge/data/icons/hicolor/128x128/apps/deluge.png']), + (os.path.join(PREFIX, 'share/icons/hicolor/16x16/apps'), [ + 'deluge/data/icons/hicolor/16x16/apps/deluge.png']), + (os.path.join(PREFIX, 'share/icons/hicolor/192x192/apps'), [ + 'deluge/data/icons/hicolor/192x192/apps/deluge.png']), + (os.path.join(PREFIX, 'share/icons/hicolor/22x22/apps'), [ + 'deluge/data/icons/hicolor/22x22/apps/deluge.png']), + (os.path.join(PREFIX, 'share/icons/hicolor/24x24/apps'), [ + 'deluge/data/icons/hicolor/24x24/apps/deluge.png']), + (os.path.join(PREFIX, 'share/icons/hicolor/256x256/apps'), [ + 'deluge/data/icons/hicolor/256x256/apps/deluge.png']), + (os.path.join(PREFIX, 'share/icons/hicolor/32x32/apps'), [ + 'deluge/data/icons/hicolor/32x32/apps/deluge.png']), + (os.path.join(PREFIX, 'share/icons/hicolor/36x36/apps'), [ + 'deluge/data/icons/hicolor/36x36/apps/deluge.png']), + (os.path.join(PREFIX, 'share/icons/hicolor/48x48/apps'), [ + 'deluge/data/icons/hicolor/48x48/apps/deluge.png']), + (os.path.join(PREFIX, 'share/icons/hicolor/64x64/apps'), [ + 'deluge/data/icons/hicolor/64x64/apps/deluge.png']), + (os.path.join(PREFIX, 'share/icons/hicolor/72x72/apps'), [ + 'deluge/data/icons/hicolor/72x72/apps/deluge.png']), + (os.path.join(PREFIX, 'share/icons/hicolor/96x96/apps'), [ + 'deluge/data/icons/hicolor/96x96/apps/deluge.png']), + (os.path.join(PREFIX, 'share/applications'), [ + 'deluge/data/share/applications/deluge.desktop']), + (os.path.join(PREFIX, 'share/pixmaps'), ['deluge/data/pixmaps/deluge.png'])] +setup( + author = "Andrew Resch, Marcos Pinto", + author_email = "andrewresch@gmail.com, markybob@dipconsultants.com", + cmdclass=cmdclass, + data_files = _data_files, + description = "GTK+ bittorrent client", + entry_points = """ + [console_scripts] + deluge = deluge.main:start_ui + deluged = deluge.main:start_daemon + """, + ext_package = "deluge", + ext_modules = [libtorrent], + fullname = "Deluge Bittorent Client", + include_package_data = True, + license = "GPLv2", + name = "deluge", + package_data = {"deluge": ["ui/gtkui/glade/*.glade", + "data/pixmaps/*.png", + "data/pixmaps/*.svg", + "data/pixmaps/flags/*.png", + "data/revision", + "plugins/*.egg", + "i18n/*.pot", + "i18n/*/LC_MESSAGES/*.mo", + "ui/webui/LICENSE", + "ui/webui/scripts/*", + "ui/webui/ssl/*", + "ui/webui/static/*.css", + "ui/webui/static/*.js", + "ui/webui/static/images/*.png", + "ui/webui/static/images/*.jpg", + "ui/webui/static/images/*.gif", + "ui/webui/static/images/tango/*.png", + "ui/webui/templates/deluge/*", + "ui/webui/templates/advanced/*.html", + "ui/webui/templates/advanced/*.css", + "ui/webui/templates/advanced/*.cfg", + "ui/webui/templates/advanced/static/*", + "ui/webui/templates/white/*" + ]}, + packages = find_packages(exclude=["plugins"]), + url = "http://deluge-torrent.org", + version = "0.6.0.0", ) + +try: + f = open("deluge/data/revision", "w") + f.write("") + f.close() +except: + pass diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index 8b1378917..000000000 --- a/src/Makefile.am +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/_dbus.py b/src/_dbus.py deleted file mode 100644 index 025e7e6d2..000000000 --- a/src/_dbus.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) Alex Dedul 2007 -# -# 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 2, 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. - -# Import all we will use in deluge -from dbus import Interface, SessionBus, version - -# Code for dbus_importing borrowed from Listen (http://listen-project.org) -# I couldn't figure out how to use dbus without breaking on versions past -# 0.80.0. I finally found a solution by reading the source code from the -# Listen project. -if version >= (0,41,0) and version < (0,80,0): - import dbus.glib -elif version >= (0,80,0): - from dbus.mainloop.glib import DBusGMainLoop - DBusGMainLoop(set_as_default=True) diff --git a/src/common.py b/src/common.py deleted file mode 100644 index cd4d7ce53..000000000 --- a/src/common.py +++ /dev/null @@ -1,252 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) Zach Tibbitts 2006 -# -# 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 2, 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. - -import os -import xdg.BaseDirectory - -PROGRAM_NAME = "Deluge" -PROGRAM_VERSION = "0.5.9.3" - -CLIENT_CODE = "DE" -CLIENT_VERSION = "".join(PROGRAM_VERSION.split('.'))+"0"*(4 - len(PROGRAM_VERSION.split('.'))) - -def windows_check(): - import platform - if platform.system() in ('Windows', 'Microsoft'): - return True - else: - return False - -import sys -if hasattr(sys, "frozen"): - INSTALL_PREFIX = '' - os.chdir(os.path.dirname(unicode(sys.executable, sys.getfilesystemencoding( )))) -else: - # the necessary substitutions are made at installation time - INSTALL_PREFIX = '@datadir@' - -if windows_check(): - if os.path.isdir(os.path.expanduser("~")): - CONFIG_DIR = os.path.join(os.path.expanduser("~"), 'deluge') - else: - CONFIG_DIR = os.path.join(INSTALL_PREFIX, 'deluge') - if not os.path.exists(CONFIG_DIR): - os.mkdir(CONFIG_DIR) -else: - CONFIG_DIR = xdg.BaseDirectory.save_config_path('deluge') - -GLADE_DIR = os.path.join(INSTALL_PREFIX, 'share', 'deluge', 'glade') -PIXMAP_DIR = os.path.join(INSTALL_PREFIX, 'share', 'deluge', 'pixmaps') -PLUGIN_DIR = os.path.join(INSTALL_PREFIX, 'share', 'deluge', 'plugins') - -def estimate_eta(state): - try: - return ftime(get_eta(state["total_wanted"], state["total_wanted_done"], - state["download_rate"])) - except ZeroDivisionError: - return _("Infinity") - -def get_eta(size, done, speed): - # raise ZeroDivisionError for Infinity in estimate_eta() - if (size - done) == 0: - raise ZeroDivisionError - return (size - done) / speed - -# Returns formatted string describing filesize -# fsize_b should be in bytes -# Returned value will be in either KB, MB, or GB -def fsize(fsize_b): - fsize_kb = fsize_b / 1024.0 - if fsize_kb < 1000: - return "%.1f %s" % (fsize_kb, _("KiB")) - fsize_mb = fsize_kb / 1024.0 - if fsize_mb < 1000: - return "%.1f %s" % (fsize_mb, _("MiB")) - fsize_gb = fsize_mb / 1024.0 - if fsize_gb < 1000: - return "%.1f %s" % (fsize_gb, _("GiB")) - fsize_tb = fsize_gb / 1024.0 - if fsize_tb < 1000: - return "%.1f %s" % (fsize_tb, _("TiB")) - fsize_pb = fsize_tb / 1024.0 - return "%.1f %s" % (fsize_pb, _("PiB")) - -# Returns a formatted string representing a percentage -def fpcnt(dec): - return '%.2f%%'%(dec * 100) - -# Returns a formatted string representing transfer speed -def fspeed(bps): - return '%s/s'%(fsize(bps)) - -def fseed(state): - return str(str(state['num_seeds']) + " (" + str(state['total_seeds']) + ")") - -def fpeer(state): - return str(str(state['num_peers']) + " (" + str(state['total_peers']) + ")") - -def ftime(seconds): - if seconds < 60: - return '%ds'%(seconds) - minutes = seconds / 60 - seconds = seconds % 60 - if minutes < 60: - return '%dm %ds'%(minutes, seconds) - hours = minutes / 60 - minutes = minutes % 60 - if hours < 24: - return '%dh %dm'%(hours, minutes) - days = hours / 24 - hours = hours % 24 - if days < 7: - return '%dd %dh'%(days, hours) - weeks = days / 7 - days = days % 7 - if weeks < 10: - return '%dw %dd'%(weeks, days) - return 'unknown' - -def fpriority(priority): - from core import PRIORITY_DICT - - return PRIORITY_DICT[priority] - -def get_glade_file(fname): - return os.path.join(GLADE_DIR, fname) - -def get_pixmap(fname): - return os.path.join(PIXMAP_DIR, fname) - -def get_logo(size): - import gtk - if windows_check(): - return gtk.gdk.pixbuf_new_from_file_at_size(get_pixmap("deluge.png"), \ - size, size) - else: - return gtk.gdk.pixbuf_new_from_file_at_size(get_pixmap("deluge.svg"), \ - size, size) - -def open_url_in_browser(link): - import threading - import webbrowser - class BrowserThread(threading.Thread): - def __init__(self, link): - threading.Thread.__init__(self) - self.url = link - def run(self): - webbrowser.open(self.url) - BrowserThread(link).start() - -def is_url(url): - import re - - return bool(re.search('^(https?|ftp)://', url)) - -def fetch_url(url): - import urllib - - try: - filename, headers = urllib.urlretrieve(url) - except IOError: - print 'Network error while trying to fetch torrent from %s' % url - else: - if filename.endswith(".torrent") or \ - headers["content-type"]=="application/x-bittorrent": - return filename - else: - print "URL doesn't appear to be a valid torrent file:", url - - return None - -def exec_command(executable, *parameters): - import os - command = [executable] - command.extend(parameters) - if windows_check(): - try: - from subprocess import Popen - Popen(command) - except: - pass - else: - try: - os.WEXITSTATUS(os.system(command[0] + " \"%s\"" %command[1])) - except OSError: - import gtk - - warning = gtk.MessageDialog(parent = None, - flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - buttons= gtk.BUTTONS_OK, - message_format='%s %s %s' % (_("External command"), - executable, _("not found")), - type = gtk.MESSAGE_WARNING) - warning.run() - warning.destroy() - -def send_info(plugins=None): - import threading - class Send_Info_Thread(threading.Thread): - def __init__(self, plugins): - threading.Thread.__init__(self) - def run(self): - import urllib - import platform - import gtk - import os - import common - - pygtk = '%i.%i.%i' %(gtk.pygtk_version[0],gtk.pygtk_version[1],gtk.pygtk_version[2]) - try: - url = "http://deluge-torrent.org/stats_get.php?processor=" + \ - platform.machine() + "&python=" + platform.python_version() \ - + "&os=" + platform.system() + "&pygtk=" + pygtk + "&plugins=" + urllib.quote_plus(plugins) - urllib.urlopen(url) - except IOError: - print "Network error while trying to send info" - else: - if not os.path.exists(CONFIG_DIR): - os.makedirs(CONFIG_DIR) - f = open(os.path.join(CONFIG_DIR, 'infosent'), 'w') - f.write("") - f.close - Send_Info_Thread(plugins).start() - -# Encryption States -class EncState: - forced, enabled, disabled = range(3) - -class EncLevel: - plaintext, rc4, both = range(3) - -class ProxyType: - none, socks4, socks5, socks5_pw, http, http_pw = range(6) - -class FileManager: - xdg, konqueror, nautilus, thunar = range(4) diff --git a/src/core.py b/src/core.py deleted file mode 100644 index 8041d0e94..000000000 --- a/src/core.py +++ /dev/null @@ -1,1266 +0,0 @@ -# -*- coding: utf-8 -*- -# core.py -# -# Copyright (C) 2006 Alon Zakai ('Kripken') -# -# 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 2, 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. - -# Deluge Library, previously known as python-libtorrent: -# -# Deluge is a Python library for torrenting, that includes -# Deluge, which is Python code, and Deluge_core, which is also a Python -# module, but written in C++, and includes the libtorrent torrent library. Only -# Deluge should be visible, and only it should be imported, in the client. -# Deluge_core contains mainly libtorrent-interfacing code, and a few other things -# that make most sense to write at that level. Deluge contains all other -# torrent-system management: queueing, configuration management, persistent -# list of torrents, etc. -# - -# Documentation: -# Torrents have 3 structures: -# 1. torrent_info - persistent data, like name, upload speed cap, etc. -# 2. core_torrent_state - transient state data from the core. This may take -# time to calculate, so we do if efficiently -# 3. supp_torrent_state - supplementary torrent data, from Deluge - -import cPickle as pickle -import os -import re -import shutil -import platform -import common -import time - -import deluge_core -import pref - -# Constants - -TORRENTS_SUBDIR = "torrentfiles" - -STATE_FILENAME = "persistent.state" -PREFS_FILENAME = "prefs.state" -DHT_FILENAME = "dht.state" - -PREF_FUNCTIONS = { - "listen_on" : deluge_core.set_listen_on, - "max_half_open" : deluge_core.set_max_half_open, - "connection_speed" : deluge_core.connection_speed, - "max_connections_global" : deluge_core.set_max_connections_global, - "max_active_torrents" : None, # no need for a function, applied constantly - "max_upload_slots_global" : deluge_core.set_max_upload_slots_global, - "auto_seed_ratio" : None, # no need for a function, applied constantly - "auto_seed_time" : None, # no need for a function, applied constantly - "max_download_speed_bps" : deluge_core.set_download_rate_limit, - "max_upload_speed_bps" : deluge_core.set_upload_rate_limit, - "enable_dht" : None, # not a normal pref in that is is applied only on start - "use_upnp" : deluge_core.use_upnp, - "use_lsd" : deluge_core.use_lsd, - "use_natpmp" : deluge_core.use_natpmp, - "use_utpex" : deluge_core.use_utpex, - "send_redund" : deluge_core.send_redund, -} - -STATE_MESSAGES = (_("Queued"), - _("Checking"), - _("Connecting"), - _("Downloading Metadata"), - _("Downloading"), - _("Finished"), - _("Seeding"), - _("Allocating")) - -# Priorities -PRIORITY_DONT_DOWNLOAD = 0 -PRIORITY_NORMAL = 1 -PRIORITY_HIGH = 2 -PRIORITY_HIGHEST = 5 - -PRIORITY_DICT = {PRIORITY_DONT_DOWNLOAD: _("Don't download"), - PRIORITY_NORMAL: _("Normal"), - PRIORITY_HIGH: _("High"), - PRIORITY_HIGHEST: _("Highest")} - -# Exceptions - -class DelugeError(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - -class InvalidEncodingError(DelugeError): - pass - -class FilesystemError(DelugeError): - pass - -# Note: this may be raised both from deluge-core.cpp and deluge.py, for -# different reasons, both related to duplicate torrents -class DuplicateTorrentError(DelugeError): - pass - -class InvalidTorrentError(DelugeError): - pass - -class InvalidUniqueIDError(DelugeError): - pass - -class InsufficientFreeSpaceError(DelugeError): - def __init__(self, free_space, needed_space): - self.free_space = free_space - self.needed_space = needed_space - def __str__(self): - return "%d %d" % self.free_space, self.needed_space + _("bytes needed") - -# A cached data item - -class cached_data: - CACHED_DATA_EXPIRATION = 1 - - def __init__(self, get_method): - self._get_method = get_method - self._cache = {} - self._expire_info = {} - - def get(self, key, cached=True): - now = time.time() - exp = self._expire_info.get(key) - if not exp or now > exp + self.CACHED_DATA_EXPIRATION or not cached: - self._cache[key] = self._get_method(key) - self._expire_info[key] = now - - return self._cache[key] - -# Persistent information for a single torrent - -class torrent_info: - def __init__(self, filename, save_dir, compact, user_paused=False): - self.filename = filename - self.save_dir = save_dir - self.compact = compact - self.user_paused = user_paused - self.uploaded_memory = 0 - self.upload_rate_limit = 0 - self.download_rate_limit = 0 - self.webseed_urls = [] - self.desired_ratio = 1.0 - self.trackers = "" - self.trackers_changed = 0 - self.seed_time = 0.0 - - self.delete_me = False # set this to true, to delete it on next sync - self.del_data = False # set this to true, to delete data on next sync - self.del_torrent = False # set this to true, to delete torrent on next sync - -# The persistent state of the torrent system. Everything in this will be pickled - -class persistent_state: - def __init__(self): - # Torrents is a dict with instance of torrent_info -> unique_ID - self.torrents = {} - - # Prepare queue (queue is pickled, just like everything else) - # queue[x] is the unique_ID of the x-th queue position. Simple. - self.queue = [] - -# The manager for the torrent system - -class Manager: - # blank_slate mode ignores the two pickle files and DHT state file, i.e. you start - # completely fresh. When quitting, the old files will be overwritten - def __init__(self, client_ID, version, user_agent, base_dir, blank_slate=False, base_change=False): - self.base_dir = base_dir - # Keeps track of DHT running state - self.dht_running = False - - # Load the preferences - self.config = pref.Preferences(os.path.join(self.base_dir, PREFS_FILENAME)) - if base_change: - self.config.set("default_torrent_path", os.path.join(self.base_dir, "torrentfiles")) - self.config.save() - TORRENTS_SUBDIR = self.config.get("default_torrent_path") - - # Ensure directories exist - if not os.path.exists(TORRENTS_SUBDIR): - os.mkdir(TORRENTS_SUBDIR) - - # Pre-initialize the core's data structures - deluge_core.pre_init(DelugeError, - InvalidEncodingError, - SystemError, - FilesystemError, - DuplicateTorrentError, - InvalidTorrentError) - - # Start up the core - deluge_core.init(client_ID, - int(version[0]), - int(version[1]), - int(version[2]), - int(version[3]), - user_agent) - - self.constants = deluge_core.constants() - - # Unique IDs are NOT in the state, since they are temporary for each session - self.unique_IDs = {} # unique_ID -> a torrent_info object, i.e. persistent data - - # Cached torrent core_states. We do not poll the core in a costly - # manner. - self.cached_core_torrent_states = \ - cached_data(deluge_core.get_torrent_state) - - # supplementary torrent states - self.supp_torrent_states = {} # unique_ID->dict of data - - # Cached torrent core_states. We do not poll the core in a costly - # manner. - self.cached_core_torrent_peer_infos = \ - cached_data(deluge_core.get_peer_info) - - # Cached torrent core_states. We do not poll the core in a costly - # manner. - self.cached_core_torrent_file_infos = \ - cached_data(deluge_core.get_file_info) - - # Apply preferences. Note that this is before any torrents are added - self.apply_prefs() - - # Event callbacks for use with plugins - self.event_callbacks = {} - - # unique_ids removed by core - self.removed_unique_ids = {} - - # unique_ids with files just removed by user - self.update_files_removed = {} - - PREF_FUNCTIONS["enable_dht"] = self.set_DHT - - # Unpickle the state, or create a new one - self.state = persistent_state() - if not blank_slate: - try: - pkl_file = open(os.path.join(self.base_dir, STATE_FILENAME), - 'rb') - state = pickle.load(pkl_file) - pkl_file.close() - - if isinstance(state.torrents, list): - # One time convert of old torrents list to dict - state.torrents = dict((x, None) for x in state.torrents) - - fr_sorted = [] - for torrent in state.torrents: - if os.path.exists(torrent.filename + ".fastresume"): - fr_sorted.insert(0, torrent) - else: - fr_sorted.append(torrent) - - # Add torrents to core and unique_IDs - for torrent in fr_sorted: - if not os.path.exists(torrent.filename): - print "Missing file: %s" % torrent.filename - continue - if torrent not in self.unique_IDs.values(): - try: - unique_ID = deluge_core.add_torrent(torrent.filename, - torrent.save_dir, - torrent.compact) - except Exception, e: - print "Unable to add torrent: ", e - - self.unique_IDs[unique_ID] = torrent - self.state.torrents[torrent] = unique_ID - - # Apply per torrent prefs after torrent added to core - self.apply_prefs_per_torrent(unique_ID) - - # Make sure the Queue is in the correct order and remove any - # entries that were not added to the session due to error. - self.state.queue = state.queue[:] - - for uid in state.queue: - if uid not in self.state.torrents: - self.state.queue.remove(uid) - - # Sync with the core: tell core about torrents, and get - # unique_IDs - self.sync() - - # Apply the queue at this time, after all is loaded and ready - self.apply_queue() - except: - pass - - def quit(self): - # Pickle the state - self.pickle_state() - - # Stop DHT, if needed - self.set_DHT(False) - - #close upnp - deluge_core.use_upnp(0) - - if self.config.get("use_compact_storage"): - for unique_ID in self.unique_IDs.keys(): - self.pause(unique_ID) - - # Save fastresume data - print "Saving fastresume data..." - self.save_fastresume_data() - - # Shutdown torrent core - print "Quitting the core..." - deluge_core.quit() - - #kill dbus on windows - if common.windows_check(): - if platform.win32_ver()[1] > '6': - os.popen4('taskkill.exe /IM dbus-daemon-deluge.exe /F') - else: - os.popen4('tskill.exe dbus-daemon-deluge') - - def pickle_state(self): - print "save uploaded memory" - import copy - state = persistent_state() - state.queue = self.state.queue[:] - - for torrent in self.state.torrents: - uid = self.state.torrents[torrent] - t = copy.copy(torrent) - try: - t.uploaded_memory = self.unique_IDs[uid].uploaded_memory +\ - self.get_core_torrent_state(uid, False)['total_payload_upload'] - except AttributeError: - t.uploaded_memory = 0 - state.torrents[t] = uid - state.queue[state.queue.index(torrent)] = t - - # Pickle the state so if we experience a crash, the latest state is - # available - print "Pickling state..." - if not os.path.exists(self.base_dir): - os.makedirs(self.base_dir) - output = open(os.path.join(self.base_dir, STATE_FILENAME), 'wb') - pickle.dump(state, output) - output.close() - - # Preference management functions - def get_config(self): - # This returns the preference object - return self.config - - def get_pref(self, key): - # Get the value from the preferences object - return self.config.get(key) - - # Get file piece range - def get_file_piece_range(self, unique_id): - try: - return deluge_core.get_file_piece_range(unique_id) - except Exception, e: - print "Unable to get file piece range:", e - - # Check if piece is finished - def has_piece(self, unique_id, piece_index): - try: - return deluge_core.has_piece(unique_id, piece_index) - except Exception, e: - print "Unable to get has piece:", e - - # Dump torrent info without adding - def dump_torrent_file_info(self, torrent): - try: - ret = deluge_core.dump_file_info(torrent) - except SystemError: - print "invalid file" - else: - return ret - - # Dump trackers from torrent file - def dump_trackers(self, torrent): - try: - return deluge_core.dump_trackers(torrent) - except Exception, e: - print "Unable to dump trackers:", e - - # Torrent addition and removal functions - - def add_torrent(self, filename, save_dir, compact, user_paused=False): - self.add_torrent_ns(filename, save_dir, compact, user_paused) - return self.sync() # Syncing will create a new torrent in the core, and return it's ID - - # When duplicate torrent error, use to find duplicate when merging tracker lists - def test_duplicate(self, torrent, unique_id): - try: - return deluge_core.test_duplicate(torrent, unique_id) - except Exception, e: - print "Unable to test duplicate:", e - - def remove_torrent(self, unique_ID, data_also, torrent_also): - temp = self.unique_IDs[unique_ID] - try: - temp_fileinfo = deluge_core.get_file_info(unique_ID) - except Exception, e: - print "Unable to get file info:", e - self.remove_torrent_ns(unique_ID, data_also) - self.sync() - - # Remove .torrent file if asked to do so - if torrent_also: - os.remove(temp.filename) - - # A function to try and reload a torrent from a previous session. This is - # used in the event that Deluge crashes and a blank state is loaded. - def add_old_torrent(self, filename, save_dir, compact): - if not filename in os.listdir(self.config.get("default_torrent_path")): - #raise InvalidTorrentError(_("File was not found") + ": " + filename) - print "File not found: ", filename - return - - full_new_name = os.path.join(self.config.get("default_torrent_path"), filename) - - # Create torrent object - new_torrent = torrent_info(full_new_name, save_dir, compact) - self.state.torrents[new_torrent] = None - - return self.sync() - - # A separate function, because people may want to call it from time to time - def save_fastresume_data(self, uid=None): - if uid == None: - for unique_ID in self.unique_IDs: - try: - state = deluge_core.get_torrent_state(unique_ID) - if not state['is_finished'] and state['state'] != 0 and state['state'] != 1: - os.remove(self.unique_IDs[unique_ID].filename + ".fastresume") - deluge_core.save_fastresume(unique_ID, self.unique_IDs[unique_ID].filename) - except OSError: - print "no old fastresume to delete" - try: - deluge_core.save_fastresume(unique_ID, self.unique_IDs[unique_ID].filename) - except: - pass - except Exception, e: - print "Unable to save fastresume: ", e - else: - # Do not save fastresume if torrent is Queued for checking or being checked - try: - state = deluge_core.get_torrent_state(uid) - if state['state'] == 0 or state['state'] == 1: - return - os.remove(self.unique_IDs[uid].filename + ".fastresume") - deluge_core.save_fastresume(uid, self.unique_IDs[uid].filename) - except OSError: - print "no old fastresume to delete" - try: - deluge_core.save_fastresume(uid, self.unique_IDs[uid].filename) - except: - pass - except Exception, e: - print "Unable to save fastresume: ", e - return True - - # State retrieval functions - - def get_state(self): - ret = deluge_core.get_session_info() - - # Get additional data from our level - ret['is_listening'] = deluge_core.is_listening() - ret['port'] = deluge_core.listening_port() - if self.dht_running == True: - ret['DHT_nodes'] = deluge_core.get_DHT_info() - - return ret - - # This is the EXTERNAL function, for the GUI. It returns the core_state + supp_state - def get_torrent_state(self, unique_ID): - # Check to see if unique_ID exists: - if unique_ID not in self.unique_IDs: - print "Asked for a torrent that doesn't exist" - return - try: - ret = self.get_core_torrent_state(unique_ID).copy() - - # Add the deluge-level things to the deluge_core data - ret.update(self.get_supp_torrent_state(unique_ID)) - - # Get queue position - torrent = self.unique_IDs[unique_ID] - ret['queue_pos'] = self.state.queue.index(torrent) + 1 - return ret - except: - return None - - def get_torrent_peer_info(self, unique_ID): - # Perhaps at some time we may add info here - return self.get_core_torrent_peer_info(unique_ID) - - def get_torrent_file_info(self, unique_ID): - return self.get_core_torrent_file_info(unique_ID) - - def get_piece_info(self, unique_ID, piece_index): - try: - return deluge_core.get_piece_info(unique_ID, piece_index) - except Exception, e: - print "Unable to get piece info:", e - - def get_all_piece_info(self, unique_ID): - try: - return deluge_core.get_all_piece_info(unique_ID) - except Exception, e: - print "Unable to get all piece info:", e - - def get_torrent_unique_id(self, torrent): - return self.state.torrents[torrent] - - # Queueing functions - - def queue_top(self, unique_ID): - torrent = self.unique_IDs[unique_ID] - self.state.queue.insert(0, - self.state.queue.pop(self.get_queue_index(torrent))) - self.apply_queue() - self.pickle_state() - - def queue_up(self, unique_ID): - torrent = self.unique_IDs[unique_ID] - curr_index = self.get_queue_index(torrent) - if curr_index > 0: - temp = self.state.queue[curr_index - 1] - self.state.queue[curr_index - 1] = torrent - self.state.queue[curr_index] = temp - self.apply_queue() - self.pickle_state() - - def queue_down(self, unique_ID): - torrent = self.unique_IDs[unique_ID] - curr_index = self.get_queue_index(torrent) - if curr_index < (len(self.state.queue) - 1): - temp = self.state.queue[curr_index + 1] - self.state.queue[curr_index + 1] = torrent - self.state.queue[curr_index] = temp - self.apply_queue() - self.pickle_state() - - def queue_bottom(self, unique_ID, enforce_queue=True): - torrent = self.unique_IDs[unique_ID] - curr_index = self.get_queue_index(torrent) - if curr_index < (len(self.state.queue) - 1): - self.state.queue.remove(torrent) - self.state.queue.append(torrent) - if enforce_queue: - self.apply_queue() - self.pickle_state() - - def clear_completed(self): - for unique_ID in self.unique_IDs: - torrent_state = self.get_core_torrent_state(unique_ID) - if torrent_state['progress'] == 1.0: - self.remove_torrent_ns(unique_ID, False, True) - self.removed_unique_ids[unique_ID] = 1 - - self.sync() - self.apply_queue() - - # Enforce the queue: pause/unpause as needed, based on queue and user_pausing - # This should be called after changes to relevant parameters (user_pausing, or - # altering max_active_torrents), or just from time to time - # ___ALL queuing code should be in this function, and ONLY here___ - def apply_queue(self): - # Counter for currently active torrent in the queue. Paused in core - # but having self.is_user_paused(unique_ID) == False is - # also considered active. - active_torrent_cnt = 0 - - # Pause and resume torrents - for torrent in self.state.queue: - unique_ID = self.state.torrents[torrent] - # Get not cached torrent state so we don't pause/resume torrents - # more than 1 time - if cached torrent_state['is_paused'] can be - # still paused after we already paused it. - torrent_state = self.get_core_torrent_state(unique_ID, False) - - if not torrent_state['is_paused'] or \ - (torrent_state['is_paused'] and not \ - self.is_user_paused(unique_ID)): - active_torrent_cnt += 1 - - if (active_torrent_cnt <= self.get_pref('max_active_torrents') or \ - self.get_pref('max_active_torrents') == -1) and \ - torrent_state['is_paused'] and not \ - self.is_user_paused(unique_ID): - # This torrent is a seed so skip all the free space checking - if torrent_state['is_finished']: - self.resume(unique_ID) - continue - - # Before we resume, we should check if the torrent is using Full Allocation - # and if there is enough space on to finish this file. - if not self.unique_IDs[unique_ID].compact: - avail = self.calc_free_space(directory = self.unique_IDs\ - [unique_ID].save_dir) - total_needed = torrent_state["total_wanted"] - torrent_state["total_wanted_done"] - if total_needed < avail: - # We have enough free space, so lets resume this torrent - self.resume(unique_ID) - else: - self.pause(unique_ID) - self.unique_IDs[unique_ID].user_paused = True - nice_need = common.fsize(total_needed) - nice_free = common.fsize(avail) - import gtk - import dialogs - gtk.gdk.threads_enter() - dialogs.show_popup_warning(None, _("There is not enough \ -free disk space to complete your download.") + "\n" + "This torrents will be \ -paused" + "\n" + _("Space Needed:") + " " + nice_need + "\n" + _("Available \ -Space:") + " " + nice_free) - gtk.gdk.threads_leave() - print "Not enough free space to resume this torrent!" - else: #We're using compact allocation so lets just resume - self.resume(unique_ID) - elif not torrent_state['is_paused'] and \ - ((active_torrent_cnt > self.get_pref('max_active_torrents') and \ - self.get_pref('max_active_torrents') != -1) or \ - self.is_user_paused(unique_ID)): - self.pause(unique_ID) - - # Handle autoseeding - downqueue as needed - if not self.get_pref('clear_max_ratio_torrents') \ - and self.get_pref('auto_seed_ratio') > 0 \ - and self.get_pref('auto_end_seeding'): - for unique_ID in self.unique_IDs: - torrent_state = self.get_core_torrent_state(unique_ID) - if (torrent_state["total_wanted"] - torrent_state["total_wanted_done"] == 0) and not torrent_state['is_paused']: - ratio = self.calc_ratio(unique_ID, torrent_state) - if ratio >= self.get_pref('auto_seed_ratio'): - self.queue_bottom(unique_ID, enforce_queue=False) # don't recurse! - self.set_user_pause(unique_ID, True, enforce_queue=False) - - if not self.get_pref('clear_max_rtime_torrents') \ - and self.get_pref('auto_seed_time') > 0 \ - and self.get_pref('auto_time_end_seeding'): - for unique_ID in self.unique_IDs: - torrent_state = self.get_core_torrent_state(unique_ID) - if (torrent_state["total_wanted"] - torrent_state["total_wanted_done"] == 0) and not torrent_state['is_paused']: - seed_time = self.unique_IDs[unique_ID].seed_time - now = time.time() - if (now - seed_time) >= (self.get_pref('auto_seed_time') * 3600): - self.queue_bottom(unique_ID, enforce_queue=False) # don't recurse! - self.set_user_pause(unique_ID, True, enforce_queue=False) - - if self.get_pref('clear_max_ratio_torrents') and self.get_pref('auto_end_seeding'): - for unique_ID in self.unique_IDs.keys(): - torrent_state = self.get_core_torrent_state(unique_ID) - if (torrent_state["total_wanted"] - torrent_state["total_wanted_done"] == 0): - ratio = self.calc_ratio(unique_ID, torrent_state) - if ratio >= self.get_pref('auto_seed_ratio'): - self.removed_unique_ids[unique_ID] = 1 - self.remove_torrent(unique_ID, False, True) - if self.get_pref('clear_max_time_torrents') and self.get_pref('auto_time_end_seeding'): - for unique_ID in self.unique_IDs.keys(): - torrent_state = self.get_core_torrent_state(unique_ID) - if (torrent_state["total_wanted"] - torrent_state["total_wanted_done"] == 0): - seed_time = self.unique_IDs[unique_ID].seed_time - now = time.time() - if (now - seed_time) >= (self.get_pref('auto_seed_time') * 3600): - self.removed_unique_ids[unique_ID] = 1 - self.remove_torrent(unique_ID, False, True) - # Event handling - - def connect_event(self, event_type, callback): - if event_type not in self.event_callbacks: - self.event_callbacks[event_type] = [] - self.event_callbacks[event_type].append(callback) - - def disconnect_event(self, event_type, callback): - if event_type in self.event_callbacks and \ - callback in self.event_callbacks[event_type]: - self.event_callbacks[event_type].remove(callback) - - def handle_events(self): - # Handle them for the backend's purposes, but still send them up in case the client - # wants to do something - show messages, for example - def pop_event(): - try: - event = deluge_core.pop_event() - except: - return None - else: - return event - - ret = [] - while True: - event = pop_event() - if event is None: - break - -# print "EVENT: ", event - - ret.append(event) - - if 'unique_ID' in event and \ - event['unique_ID'] not in self.unique_IDs: - continue - - if event['event_type'] in self.event_callbacks: - for callback in self.event_callbacks[event['event_type']]: - callback(event) - - if event['event_type'] is self.constants['EVENT_TORRENT_PAUSED'] or \ - event['event_type'] is self.constants['EVENT_FINISHED_CHECKING']: - self.save_fastresume_data(event['unique_ID']) - - if event['event_type'] is self.constants['EVENT_FINISHED']: - # save fast resume once torrent finishes so as to not recheck - # seed if client crashes - self.save_fastresume_data(event['unique_ID']) - if event['message'] == "torrent has finished downloading": - self.unique_IDs[event['unique_ID']].seed_time = time.time() - # Queue seeding torrent to bottom if needed - if self.get_pref('queue_seeds_to_bottom'): - self.queue_bottom(event['unique_ID']) - - - elif event['event_type'] is self.constants['EVENT_FILE_ERROR']: - import gtk - import dialogs - gtk.gdk.threads_enter() - dialogs.show_popup_warning(None, event['message']) - gtk.gdk.threads_leave() - - elif event['event_type'] is self.constants['EVENT_TRACKER_ANNOUNCE']: - self.set_supp_torrent_state_val(event['unique_ID'], - "tracker_status", - _("Announce sent")) - elif event['event_type'] is self.constants['EVENT_TRACKER_REPLY']: - self.set_supp_torrent_state_val(event['unique_ID'], - "tracker_status", - _("Announce OK")) - if event['num_complete'] == -1 or event['num_incomplete'] == -1: - self.scrape_tracker(event['unique_ID']) - - elif event['event_type'] is self.constants['EVENT_TRACKER_ALERT']: - match = re.search('tracker:\s*".*"\s*(.*)', event["message"]) - message = match and match.groups()[0] or "" - try: - tracker_status = "%s: %s (%s=%s, %s=%s)" % \ - (_("Alert"), message, - _("HTTP code"), event["status_code"], - _("times in a row"), event["times_in_row"]) - - self.set_supp_torrent_state_val(event['unique_ID'], - "tracker_status", - tracker_status) - except UnicodeDecodeError: - print "There was a problem displaying a tracker alert. Most\ -likely the tracker did not responsd in utf-8." - - elif event['event_type'] is self.constants['EVENT_TRACKER_WARNING']: - # Probably will need proper formatting later, not tested yet - try: - tracker_status = '%s: %s' % (_("Warning"), event["message"]) - - self.set_supp_torrent_state_val(event['unique_ID'], - "tracker_status", - tracker_status) - except UnicodeDecodeError: - print "There was a problem displaying a tracker alert. Most\ -likely the tracker did not responsd in utf-8." - - return ret - - # Priorities functions - def clear_update_files_removed(self): - self.update_files_removed = {} - - def prioritize_files(self, unique_ID, priorities, update_files_removed=False): - assert(len(priorities) == \ - self.get_core_torrent_state(unique_ID)['num_files']) - self.unique_IDs[unique_ID].priorities = priorities[:] - try: - deluge_core.prioritize_files(unique_ID, priorities) - except Exception, e: - print "Unable to prioritize files:", e - - if update_files_removed: - self.update_files_removed[unique_ID] = 1 - - if self.get_pref('prioritize_first_last_pieces'): - self.prioritize_first_last_pieces(unique_ID) - - def get_priorities(self, unique_ID): - try: - return self.unique_IDs[unique_ID].priorities[:] - except AttributeError: - # return normal priority for all files by default - - num_files = self.get_core_torrent_state(unique_ID)['num_files'] - return [PRIORITY_NORMAL] * num_files - - def prioritize_first_last_pieces(self, unique_ID): - """Try to prioritize first and last pieces of each file in torrent - - Currently it tries to prioritize 1% in the beginning and in the end - of each file in the torrent - - """ - try: - deluge_core.prioritize_first_last_pieces(unique_ID, - self.unique_IDs[unique_ID].priorities) - except Exception, e: - print "Unable to prioritize first and last pieces:", e - - # Advanced statistics - these may be SLOW. The client should call these only - # when needed, and perhaps only once in a long while (they are mostly just - # approximations anyhow - - def calc_swarm_speed(self, unique_ID): - pieces_per_sec = deluge_stats.calc_swarm_speed(self.get_core_torrent_peer_info(unique_ID)) - piece_length = self.get_core_torrent_state(unique_ID) - - return pieces_per_sec * piece_length - - # Miscellaneous minor functions - - def set_user_pause(self, unique_ID, new_value, enforce_queue=True): - if self.config.get("max_active_torrents") == 0: - self.config.set("max_active_torrents", \ - self.config.get("max_active_torrents_tmp")) - self.apply_prefs() - try: - self.unique_IDs[unique_ID].user_paused = new_value - if enforce_queue: - self.apply_queue() - self.pickle_state() - except: - print "pause failed\n" - - def set_ratio(self, unique_ID, num): - try: - deluge_core.set_ratio(unique_ID, float(num)) - except Exception, e: - print "Unable to set ratio: ", e - - def is_user_paused(self, unique_ID): - return self.unique_IDs[unique_ID].user_paused - - def get_num_torrents(self): - return deluge_core.get_num_torrents() - - def get_queue(self): - return self.state.queue - - def update_tracker(self, unique_ID): - try: - deluge_core.reannounce(unique_ID) - except Exception, e: - print "Unable to reannounce: ", e - - def scrape_tracker(self, unique_ID): - try: - deluge_core.scrape_tracker(unique_ID) - except Exception, e: - print "Unable to scrape tracker ", e - - def pause(self, unique_ID): - try: - state = self.get_torrent_state(unique_ID) - if not state["is_paused"]: - deluge_core.pause(unique_ID) - except: - print "pause failed\n" - - def resume(self, unique_ID): - state = self.get_torrent_state(unique_ID) - if state["is_paused"]: - try: - deluge_core.resume(unique_ID) - # We have to re-apply per torrent settings after resume. This has to - # be done until ticket #118 in libtorrent is fixed. - self.apply_prefs_per_torrent(unique_ID) - except: - print "pause failed\n" - - def pause_all(self): - if self.config.get('max_active_torrents') != 0: - self.config.set('max_active_torrents_tmp', \ - self.config.get('max_active_torrents')) - self.config.set('max_active_torrents', 0) - self.apply_prefs() - - def resume_all(self): - if self.config.get('max_active_torrents') == 0: - self.config.set('max_active_torrents', \ - self.config.get('max_active_torrents_tmp')) - self.apply_prefs() - - def move_storage(self, unique_ID, directory): - try: - deluge_core.move_storage(unique_ID, directory) - except Exception, e: - print "Unable to move storage: ", e - - #################### - # Internal functions - #################### - - def get_core_torrent_state(self, unique_ID, cached=True): - return self.cached_core_torrent_states.get(unique_ID, cached) - - def get_supp_torrent_state(self, unique_ID): - return self.supp_torrent_states.get(unique_ID, {}) - - def set_supp_torrent_state_val(self, unique_ID, key, val): - if unique_ID not in self.supp_torrent_states: - self.supp_torrent_states[unique_ID] = {} - - self.supp_torrent_states[unique_ID][key] = val - - def get_core_torrent_peer_info(self, unique_ID): - return self.cached_core_torrent_peer_infos.get(unique_ID) - - def get_core_torrent_file_info(self, unique_ID): - return self.cached_core_torrent_file_infos.get(unique_ID) - - # Functions for checking if enough space is available - - def calc_free_space(self, directory): - if not common.windows_check(): - import statvfs - try: - dir_stats = os.statvfs(directory) - except: - return 0 - block_size = dir_stats[statvfs.F_BSIZE] - avail_blocks = dir_stats[statvfs.F_BAVAIL] - return long(block_size * avail_blocks) - else: - import string - import win32file - sectorsPerCluster, bytesPerSector, numFreeClusters, \ - totalNumClusters_Not_Used = win32file.GetDiskFreeSpace(\ - directory[0] + ":\\") - sectorsPerCluster = long(sectorsPerCluster) - bytesPerSector = long(bytesPerSector) - numFreeClusters = long(numFreeClusters) - return long(numFreeClusters * sectorsPerCluster * bytesPerSector) - - # Non-syncing functions. Used when we loop over such events, and sync manually at the end - - def add_torrent_ns(self, filename, save_dir, compact, user_paused): - # Cache torrent file - (temp, filename_short) = os.path.split(filename) - - # if filename_short in os.listdir(self.base_dir + "/" + TORRENTS_SUBDIR): - # raise DuplicateTorrentError("Duplicate Torrent, it appears: " + filename_short) - - full_new_name = os.path.join(self.config.get("default_torrent_path"), filename_short) - - try: - shutil.copy(filename, full_new_name) - except Exception, e: - if str(e).find('are the same file'): - pass - else: - raise - - # Create torrent object - new_torrent = torrent_info(full_new_name, save_dir, compact, user_paused) - self.state.torrents[new_torrent] = None - - def remove_torrent_ns(self, unique_ID, data_also, torrent_also=False): - self.unique_IDs[unique_ID].delete_me = True - self.unique_IDs[unique_ID].del_data = data_also - self.unique_IDs[unique_ID].del_torrent = torrent_also - - # Sync the state.torrents and unique_IDs lists with the core - # ___ALL syncing code with the core is here, and ONLY here___ - # Also all self-syncing is done here (various lists) - - ## - ## I had to make some changes here to get things to work properly - ## Some of these changes may be hack-ish, so look at them and make - ## sure nothing is wrong. - ## - def sync(self, called_on_start=False): - ret = None # We return new added unique ID(s), or None - no_space = False - - to_remove = [] - # Add torrents to core and unique_IDs - for torrent in self.state.torrents: - if not os.path.exists(torrent.filename): - print "Missing file: %s" % torrent.filename - to_remove.append(torrent) - continue - if torrent not in self.unique_IDs.values(): - try: - unique_ID = deluge_core.add_torrent(torrent.filename, - torrent.save_dir, - torrent.compact) - except DelugeError, e: - del self.state.torrents[torrent] - raise e - continue - except Exception, e: - print "Unable to add torrent: ", e - to_remove.append(torrent) - continue - - ret = unique_ID - self.unique_IDs[unique_ID] = torrent - self.state.torrents[torrent] = unique_ID - - # Apply per torrent prefs after torrent added to core - self.apply_prefs_per_torrent(unique_ID) - #remove fastresume for non-seed - try: - torrent_state = self.get_core_torrent_state(unique_ID) - except: - pass - else: - if not torrent_state['is_finished']: - try: - os.remove(self.unique_IDs[unique_ID].filename + ".fastresume") - except: - pass - - # Remove torrents from self.state because they were not added to the - # libtorrent session. - for torrent in to_remove: - del self.state.torrents[torrent] - - # Remove torrents from core, unique_IDs and queue - to_delete = [] - for unique_ID in self.unique_IDs.keys(): -# print torrent - if self.unique_IDs[unique_ID].delete_me: - deluge_core.remove_torrent(unique_ID, \ - self.unique_IDs[unique_ID].del_data) - to_delete.append(unique_ID) - - for unique_ID in to_delete: - del self.state.torrents[self.unique_IDs[unique_ID]] - self.state.queue.remove(self.unique_IDs[unique_ID]) - try: - if self.unique_IDs[unique_ID].del_torrent: - os.remove(self.unique_IDs[unique_ID].filename) - except: - pass - # Remove .fastresume - try: - # Must be after removal of the torrent, because that saves a new .fastresume - os.remove(self.unique_IDs[unique_ID].filename + ".fastresume") - except OSError: - pass # Perhaps there never was one to begin with - del self.unique_IDs[unique_ID] - - # Add torrents to queue - at the end, of course - for torrent in self.unique_IDs.values(): - if torrent not in self.state.queue: - if self.get_pref('queue_above_completed') and \ - len(self.state.queue) > 0 and not called_on_start: - for index, torrent_tmp in enumerate(self.state.queue): - unique_ID = self.state.torrents[torrent_tmp] - torrent_state = self.get_core_torrent_state(unique_ID) - if torrent_state['progress'] == 1.0: - break - if torrent_state['progress'] == 1.0: - self.state.queue.insert(index, torrent) - else: - self.state.queue.append(torrent) - else: - self.state.queue.append(torrent) - - # run through queue, remove those that no longer exists - to_delete = [] - for torrent in self.state.queue: - if torrent not in self.state.torrents: - to_delete.append(torrent) - - for torrent in to_delete: - self.state.queue.remove(torrent) - - assert(len(self.unique_IDs) == len(self.state.torrents)) - - assert(len(self.unique_IDs) == len(self.state.queue)) - assert(len(self.unique_IDs) == deluge_core.get_num_torrents()) - - #if no_space: - #self.apply_queue() - - self.pickle_state() - - return ret - - def get_queue_index(self, torrent): - return self.state.queue.index(torrent) - - def apply_prefs(self): - print "Applying preferences" - - for pref in PREF_FUNCTIONS: - if PREF_FUNCTIONS[pref] is not None: - if (PREF_FUNCTIONS[pref] == PREF_FUNCTIONS["listen_on"]): - if not self.get_pref("random_port"): - PREF_FUNCTIONS[pref](self.get_pref(pref)) - else: - if deluge_core.listening_port() != 0: - if self.get_pref("listen_on")[0] <= deluge_core.listening_port() <= self.get_pref("listen_on")[1]: - import random - randrange = lambda: random.randrange(49152, 65535) - ports = [randrange(), randrange()] - ports.sort() - deluge_core.set_listen_on(ports) - - else: - import random - randrange = lambda: random.randrange(49152, 65535) - ports = [randrange(), randrange()] - ports.sort() - deluge_core.set_listen_on(ports) - else: - PREF_FUNCTIONS[pref](self.get_pref(pref)) - - # We need to reapply priorities to files and per torrent options after - # preferences were changed. - for unique_ID in self.unique_IDs: - self.prioritize_files(unique_ID, self.get_priorities(unique_ID)) - self.apply_prefs_per_torrent(unique_ID) - - def apply_prefs_per_torrent(self, unique_ID): - self.set_max_connections_per_torrent(unique_ID, - self.get_pref("max_connections_per_torrent")) - self.set_max_upload_slots_per_torrent(unique_ID, - self.get_pref("max_upload_slots_per_torrent")) - - def set_DHT(self, start=False): - if start and not self.dht_running: - print "Starting DHT..." - deluge_core.start_DHT(os.path.join(self.base_dir, DHT_FILENAME)) - self.dht_running = True - elif not start and self.dht_running: - print "Stopping DHT..." - deluge_core.stop_DHT(os.path.join(self.base_dir, DHT_FILENAME)) - self.dht_running = False - - # Calculations - - def calc_ratio(self, unique_ID, torrent_state): - try: - up = float((self.unique_IDs[unique_ID].uploaded_memory + self.get_core_torrent_state(unique_ID, False)['total_upload']) / 1024) - except AttributeError: - up = 0 - - down = float(torrent_state["total_done"] / 1024) - try: - ret = up/down - except: - ret = 0.0 - - return ret - - def create_torrent(self, filename, source_directory, trackers, comments=None, - piece_size=32, author="Deluge", private=False, webseeds=None): - return deluge_core.create_torrent(filename, source_directory, trackers, comments, piece_size, author, private, webseeds) - - # Creates/resets the IP filter list - def reset_ip_filter(self): - return deluge_core.reset_IP_filter() - - # Adds an IP range (as two dotted quad strings) to the filter - def add_range_to_ip_filter(self, start, end): - return deluge_core.add_range_to_IP_filter(start, end) - - def set_ip_filter(self): - return deluge_core.set_IP_filter() - - def proxy_settings(self, server, login, paswd, portnum, proxytype, proxy): - return deluge_core.proxy_settings(server, login, paswd, portnum, proxytype, proxy) - - def pe_settings(self, out_enc_policy, in_enc_policy, allowed_enc_level, prefer_rc4): - return deluge_core.pe_settings(out_enc_policy, in_enc_policy, allowed_enc_level, prefer_rc4) - - def get_trackers(self, unique_ID): - if self.unique_IDs[unique_ID].trackers: - return self.unique_IDs[unique_ID].trackers - else: - return deluge_core.get_trackers(unique_ID) - - def replace_trackers(self, unique_ID, trackerslist): - try: - self.unique_IDs[unique_ID].trackers = trackerslist - self.unique_IDs[unique_ID].trackers_changed = 1 - return deluge_core.replace_trackers(unique_ID, trackerslist) - except: - pass - - def set_priv(self, unique_ID, on_off): - return deluge_core.set_priv(unique_ID, on_off) - - def set_max_connections_per_torrent(self, unique_ID, max_connections): - return deluge_core.set_max_connections_per_torrent(unique_ID, - max_connections) - - def set_max_upload_slots_per_torrent(self, unique_ID, max_upload_slots): - return deluge_core.set_max_upload_slots_per_torrent(unique_ID, - max_upload_slots) - - def set_per_upload_rate_limit(self, unique_ID, speed): - return deluge_core.set_per_upload_rate_limit(unique_ID, speed) - - def set_per_download_rate_limit(self, unique_ID, speed): - return deluge_core.set_per_download_rate_limit(unique_ID, speed) - - def get_per_upload_rate_limit(self, unique_ID): - return deluge_core.get_per_upload_rate_limit(unique_ID) - - def get_per_download_rate_limit(self, unique_ID): - return deluge_core.get_per_download_rate_limit(unique_ID) - - def add_url_seed(self, unique_ID, address): - return deluge_core.add_url_seed(unique_ID, address) - - def get_torrent_path(self, unique_ID): - torrent_path = self.unique_IDs[unique_ID].save_dir - torrent_state = self.get_torrent_state(unique_ID) - if torrent_state["num_files"] > 1: - file = self.get_torrent_file_info(unique_ID)[0] - torrent_path = os.path.join(torrent_path, - file["path"].split("/", 1)[0]) - return torrent_path - - def rename_file(self, unique_ID, filename, filesize): - return deluge_core.remap_files(unique_ID, filename, filesize) diff --git a/src/deluge_core.cpp b/src/deluge_core.cpp deleted file mode 100644 index b1ae82fe0..000000000 --- a/src/deluge_core.cpp +++ /dev/null @@ -1,2706 +0,0 @@ -/* - * Copyright 2006 Alon Zakai ('Kripken') - * - * 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 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. - * - * Thank You: Some code portions were derived from BSD-licensed work by - * Arvid Norberg, and GPL-licensed work by Christophe Dumez - */ - -//------------------ -// TODO: -// -// The DHT capability requires UDP. We need to check that this port is in fact -// open, just like the normal TCP port for bittorrent. -// -//----------------- -#include -#if defined(_WIN32) -# if defined(socklen_t) -# undef socklen_t -# endif -#endif -#ifdef DELUGE_CORE_DEBUG -#include -#endif -#include -#include -#include - -#include "libtorrent/entry.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/identify_client.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/storage.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/ip_filter.hpp" -#include "libtorrent/upnp.hpp" -#include "libtorrent/file_pool.hpp" -#include "libtorrent/natpmp.hpp" -#include "libtorrent/size_type.hpp" -#include "libtorrent/extensions/metadata_transfer.hpp" -#include "libtorrent/extensions/ut_pex.hpp" -using namespace boost::filesystem; -using namespace libtorrent; - -//---------------- -// CONSTANTS -//---------------- - -#ifdef AMD64 -#define python_long int -#else -#define python_long long -#endif - -#define EVENT_NULL 0 -#define EVENT_FINISHED 1 -#define EVENT_PEER_ERROR 2 -#define EVENT_INVALID_REQUEST 3 -#define EVENT_FILE_ERROR 4 -#define EVENT_HASH_FAILED_ERROR 5 -#define EVENT_PEER_BAN_ERROR 6 -#define EVENT_FASTRESUME_REJECTED_ERROR 8 -#define EVENT_TRACKER_ANNOUNCE 9 -#define EVENT_TRACKER_REPLY 10 -#define EVENT_TRACKER_ALERT 11 -#define EVENT_TRACKER_WARNING 12 -#define EVENT_OTHER 13 -#define EVENT_STORAGE_MOVED 14 -#define EVENT_PIECE_FINISHED 15 -#define EVENT_BLOCK_DOWNLOADING 16 -#define EVENT_BLOCK_FINISHED 17 -#define EVENT_PEER_BLOCKED 18 -#define EVENT_LISTEN_FAILED 19 -#define EVENT_FINISHED_CHECKING 20 -#define EVENT_TORRENT_PAUSED 21 - -#define STATE_QUEUED 0 -#define STATE_CHECKING 1 -#define STATE_CONNECTING 2 -#define STATE_DOWNLOADING_META 3 -#define STATE_DOWNLOADING 4 -#define STATE_FINISHED 5 -#define STATE_SEEDING 6 -#define STATE_ALLOCATING 7 - -#define DHT_ROUTER_PORT 6881 - -//----------------- -// TYPES -//----------------- - -typedef long unique_ID_t; -typedef std::string torrent_name_t; - -struct torrent_t -{ - torrent_handle handle; - unique_ID_t unique_ID; -}; - -typedef std::vector torrents_t; -typedef torrents_t::iterator torrents_t_iterator; - -//--------------------------- -// MODULE-GLOBAL VARIABLES -//--------------------------- - -long M_unique_counter = 0; -session_settings *M_settings = NULL; -pe_settings *M_pe_settings = NULL; -proxy_settings *M_proxy_settings = NULL; -session *M_ses = NULL; -PyObject *M_constants = NULL; -ip_filter *M_the_filter = NULL; -torrents_t *M_torrents = NULL; - -//------------------------ -// Exception types & macro -//------------------------ - -static PyObject *DelugeError = NULL; -static PyObject *InvalidEncodingError = NULL; -static PyObject *FilesystemError = NULL; -static PyObject *SystemError = NULL; -static PyObject *DuplicateTorrentError = NULL; -static PyObject *InvalidTorrentError = NULL; - -#define RAISE_PTR(e,s) { printf("Raising error: %s\r\n", s); PyErr_SetString(e, s); return NULL; } -#define RAISE_INT(e,s) { printf("Raising error: %s\r\n", s); PyErr_SetString(e, s); return -1; } - -//--------------------- -// Internal functions -//--------------------- - -bool empty_name_check(const std::string & name) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " empty_name_check()" << std::endl; -#endif - return 1; -} - - -long handle_exists(torrent_handle &handle) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " handle_exists()" << std::endl; -#endif - for (unsigned long i = 0; i < M_torrents->size(); i++) - if ((*M_torrents)[i].handle == handle) - return 1; - - return 0; -} - - -long get_torrent_index(torrent_handle &handle) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " get_torrent_index()" << std::endl; -#endif - for (unsigned long i = 0; i < M_torrents->size(); i++) - if ((*M_torrents)[i].handle == handle) - { - // printf("Found: %li\r\n", i); - return i; - } - - RAISE_INT(DelugeError, "Handle not found."); -} - -long get_index_from_unique_ID(long unique_ID) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " get_index_from_unique_ID()" << std::endl; -#endif - try{ - for (unsigned long i = 0; i < M_torrents->size(); i++) - if ((*M_torrents)[i].unique_ID == unique_ID) - return i; - RAISE_INT(DelugeError, "No such unique_ID."); - } - catch(invalid_handle&) - { - printf("invalid handle error on get_index_from_unique_ID. call batman.\n"); - } - catch(...) - { - printf("unknown error on get_index_from_unique_ID. call batman.\n"); - } -} - -partial_piece_info internal_get_piece_info(torrent_handle h, long piece_index) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " internal_get_piece_info()" << std::endl; -#endif - std::vector queue; - std::vector& q = queue; - h.get_download_queue(q); - for (unsigned long i = 0; i < q.size(); i++) - { - if ((long)q[i].piece_index == piece_index) return queue[i]; - } -} - -torrent_info internal_get_torrent_info(std::string const& torrent_name) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " internal_get_torrent_info()" << std::endl; -#endif - std::ifstream in(torrent_name.c_str(), std::ios_base::binary); - in.unsetf(std::ios_base::skipws); - entry e = bdecode(std::istream_iterator(in), std::istream_iterator()); - - torrent_info t(e); - - return t; -} - -long internal_add_torrent(std::string const& torrent_name, -bool compact_mode, -boost::filesystem::path const& save_path) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " internal_add_torrent()" << std::endl; -#endif - - std::ifstream in(torrent_name.c_str(), std::ios_base::binary); - in.unsetf(std::ios_base::skipws); - entry e; - e = bdecode(std::istream_iterator(in), std::istream_iterator()); - - boost::intrusive_ptr t(new torrent_info(e)); - - entry resume_data; - try - { - std::stringstream s; - s << torrent_name << ".fastresume"; - boost::filesystem::ifstream resumeFile(s.str(), std::ios_base::binary); - resumeFile.unsetf(std::ios_base::skipws); - resume_data = bdecode(std::istream_iterator(resumeFile), - std::istream_iterator()); - } - catch (invalid_encoding&) - { - } - catch (invalid_handle&) - { - } - catch (boost::filesystem::filesystem_error&) {} - - // Create new torrent object - - torrent_t new_torrent; - libtorrent::storage_mode_t storage_mode; - if (compact_mode){ - storage_mode = storage_mode_compact; - } else { - storage_mode = storage_mode_sparse; - } - try{ - torrent_handle h = M_ses->add_torrent(t, save_path, resume_data, storage_mode); - // h.set_max_connections(60); // at some point we should use this - h.set_max_uploads(-1); - h.resolve_countries(true); - new_torrent.handle = h; - new_torrent.unique_ID = M_unique_counter; - M_unique_counter++; - M_torrents->push_back(new_torrent); - return (new_torrent.unique_ID); - } - catch (invalid_encoding&) - { RAISE_PTR(InvalidEncodingError, ""); } - catch (invalid_handle&) - { printf("invalid handle error on add_torrent"); } - catch (invalid_torrent_file&) - { RAISE_PTR(InvalidTorrentError, ""); } - catch (boost::filesystem::filesystem_error&) - { RAISE_PTR(FilesystemError, ""); } - catch (duplicate_torrent&) - { RAISE_PTR(DuplicateTorrentError, "libtorrent reports this is a duplicate torrent"); } - catch (...) {} -} - - -void internal_remove_torrent(long index, int delete_files) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " internal_remove_torrent()" << std::endl; -#endif - assert(index < M_torrents->size()); - - torrent_handle& h = M_torrents->at(index).handle; - M_ses->remove_torrent(h, delete_files); - - torrents_t_iterator it = M_torrents->begin() + index; - M_torrents->erase(it); -} - - -long get_peer_index(tcp::endpoint addr, std::vector const& peers) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " get_peer_index()" << std::endl; -#endif - long index = -1; - - for (unsigned long i = 0; i < peers.size(); i++) - if (peers[i].ip == addr) - index = i; - - return index; -} - -bool internal_has_piece(std::vector const& pieces, long index) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " internal_has_piece()" << std::endl; -#endif - return pieces[index]; -} - -// The following function contains code by Christophe Dumez and Arvid Norberg -void internal_add_files(torrent_info& t, -boost::filesystem::path const& p, -boost::filesystem::path const& l) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " internal_add_files()" << std::endl; -#endif - // change default checker, perhaps? - boost::filesystem::path f(p / l); - if (is_directory(f)) - { - for (boost::filesystem::directory_iterator i(f), end; i != end; ++i) - internal_add_files(t, p, l / i->leaf()); - } else - t.add_file(l, file_size(f)); -} - - -long count_DHT_peers(entry &state) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " count_DHT_peers()" << std::endl; -#endif - long num_peers = 0; - entry *nodes = state.find_key("nodes"); - if (nodes) - { - entry::list_type &peers = nodes->list(); - - num_peers = peers.size(); - } - - return num_peers; -} - - -//===================== -// External functions -//===================== - -static PyObject *torrent_pre_init(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_pre_init()" << std::endl; -#endif - if (!PyArg_ParseTuple(args, "OOOOOO", &DelugeError, - &InvalidEncodingError, - &SystemError, - &FilesystemError, - &DuplicateTorrentError, - &InvalidTorrentError)) - return NULL; - - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_init(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_init()" << std::endl; -#endif - printf("deluge_core; using libtorrent %s. Compiled %s NDEBUG.\r\n", - LIBTORRENT_VERSION, -#ifdef NDEBUG - "with" -#else - "without" -#endif - ); - - // Tell Boost that we are on *NIX, so bloody '.'s are ok inside a directory name! - boost::filesystem::path::default_name_check(empty_name_check); - - char *client_ID, *user_agent; - python_long v1,v2,v3,v4; - - if (!PyArg_ParseTuple(args, "siiiis", &client_ID, &v1, &v2, &v3, &v4, &user_agent)) - return NULL; - - M_settings = new session_settings; - M_ses = new session(fingerprint(client_ID, v1, v2, v3, v4)); - - M_torrents = new torrents_t; - M_torrents->reserve(10); // pretty cheap, just 10 - - // Init values - - M_settings->user_agent = std::string(user_agent); - M_settings->stop_tracker_timeout = 5; - M_settings->lazy_bitfields = 1; -#if defined(_WIN32) - DWORD windows_version = ::GetVersion(); - if ((windows_version & 0xff) >= 6) - { - // on vista the limit is 5 (in home edition) - M_ses->set_max_half_open_connections(4); - } - else - { - // on XP SP2 it's 10 - M_ses->set_max_half_open_connections(8); - } -#endif - - M_ses->set_download_rate_limit(-1); - M_ses->set_upload_rate_limit(-1); - - M_ses->set_settings(*M_settings); - M_ses->set_severity_level(alert::debug); - - M_ses->add_extension(&libtorrent::create_metadata_plugin); - - M_constants = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i}", - "EVENT_NULL", EVENT_NULL, - "EVENT_FINISHED", EVENT_FINISHED, - "EVENT_PEER_ERROR", EVENT_PEER_ERROR, - "EVENT_INVALID_REQUEST", EVENT_INVALID_REQUEST, - "EVENT_FILE_ERROR", EVENT_FILE_ERROR, - "EVENT_HASH_FAILED_ERROR", EVENT_HASH_FAILED_ERROR, - "EVENT_PEER_BAN_ERROR", EVENT_PEER_BAN_ERROR, - "EVENT_FASTRESUME_REJECTED_ERROR", EVENT_FASTRESUME_REJECTED_ERROR, - "EVENT_TRACKER_ANNOUNCE", EVENT_TRACKER_ANNOUNCE, - "EVENT_TRACKER_REPLY", EVENT_TRACKER_REPLY, - "EVENT_TRACKER_ALERT", EVENT_TRACKER_ALERT, - "EVENT_TRACKER_WARNING", EVENT_TRACKER_WARNING, - "EVENT_OTHER", EVENT_OTHER, - "EVENT_STORAGE_MOVED", EVENT_STORAGE_MOVED, - "EVENT_PIECE_FINISHED", EVENT_PIECE_FINISHED, - "EVENT_BLOCK_DOWNLOADING", EVENT_BLOCK_DOWNLOADING, - "EVENT_BLOCK_FINISHED", EVENT_BLOCK_FINISHED, - "EVENT_PEER_BLOCKED", EVENT_PEER_BLOCKED, - "EVENT_LISTEN_FAILED", EVENT_LISTEN_FAILED, - "EVENT_FINISHED_CHECKING", EVENT_FINISHED_CHECKING, - "EVENT_TORRENT_PAUSED", EVENT_TORRENT_PAUSED, - "STATE_QUEUED", STATE_QUEUED, - "STATE_CHECKING", STATE_CHECKING, - "STATE_CONNECTING", STATE_CONNECTING, - "STATE_DOWNLOADING_META", STATE_DOWNLOADING_META, - "STATE_DOWNLOADING", STATE_DOWNLOADING, - "STATE_FINISHED", STATE_FINISHED, - "STATE_SEEDING", STATE_SEEDING, - "STATE_ALLOCATING", STATE_ALLOCATING); - - Py_INCREF(Py_None); return Py_None; -}; - -static PyObject *torrent_quit(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_quit()" << std::endl; -#endif - printf("core: removing torrents...\r\n"); - delete M_torrents; - printf("core: removing settings...\r\n"); - delete M_settings; - printf("core: shutting down session...\r\n"); - delete M_ses; // 100% CPU... - Py_DECREF(M_constants); - - printf("core shut down.\r\n"); - - Py_INCREF(Py_None); return Py_None; -}; - -static PyObject *torrent_save_fastresume(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_save_fastresume()" << std::endl; -#endif - python_long unique_ID; - const char *torrent_name; - if (!PyArg_ParseTuple(args, "is", &unique_ID, &torrent_name)) - return NULL; - - try{ - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_handle& h = M_torrents->at(index).handle; - // For valid torrents, save fastresume data - if (h.is_valid() && h.has_metadata()) - { - entry data = h.write_resume_data(); - std::stringstream s; - s << torrent_name << ".fastresume"; - boost::filesystem::ofstream out(s.str(), std::ios_base::binary); - out.unsetf(std::ios_base::skipws); - bencode(std::ostream_iterator(out), data); - - } - } - catch(...){ - printf("Fast resume saving failed\n"); - } - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_set_max_half_open(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_max_half_open()" << std::endl; -#endif - python_long arg; - if (!PyArg_ParseTuple(args, "i", &arg)) - return NULL; -#if defined(_WIN32) - DWORD windows_version = ::GetVersion(); - if ((windows_version & 0xff) >= 6) - { - // on vista the limit is 5 (in home edition) - if (arg > 4) - { - arg = 4; - } - else if (arg = -1) - { - arg = 4; - } - } - else - { - // on XP SP2 it's 10 - if (arg > 8) - { - arg = 8; - } - else if (arg = -1) - { - arg = 8; - } - } -#endif - M_ses->set_max_half_open_connections(arg); - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_connection_speed(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_connection_speed()" << std::endl; -#endif - python_long arg; - if (!PyArg_ParseTuple(args, "i", &arg)) - return NULL; - M_settings->connection_speed = arg; - M_ses->set_settings(*M_settings); - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_set_download_rate_limit(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_download_rate_limit()" << std::endl; -#endif - python_long arg; - if (!PyArg_ParseTuple(args, "i", &arg)) - return NULL; - - M_ses->set_download_rate_limit(arg); - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_set_upload_rate_limit(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_upload_rate_limit()" << std::endl; -#endif - python_long arg; - if (!PyArg_ParseTuple(args, "i", &arg)) - return NULL; - - M_ses->set_upload_rate_limit(arg); - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_set_per_upload_rate_limit(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_per_upload_rate_limit()" << std::endl; -#endif - python_long unique_ID, speed; - if (!PyArg_ParseTuple(args, "ii", &unique_ID, &speed)) - return NULL; - if (speed != -1) - speed = speed * 1024; - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - if (M_torrents->at(index).handle.is_valid()) - M_torrents->at(index).handle.set_upload_limit(speed); - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_get_per_upload_rate_limit(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_get_per_upload_rate_limit()" << std::endl; -#endif - python_long unique_ID; - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - if (M_torrents->at(index).handle.is_valid()) - return Py_BuildValue("i", (python_long)M_torrents->at(index).handle.upload_limit()); - else{ - Py_INCREF(Py_None); return Py_None; - } -} - -static PyObject *torrent_set_per_download_rate_limit(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_per_download_rate_limit()" << std::endl; -#endif - python_long unique_ID, speed; - - if (!PyArg_ParseTuple(args, "ii", &unique_ID, &speed)) - return NULL; - if (speed != -1) - speed = speed * 1024; - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - if (M_torrents->at(index).handle.is_valid()) - M_torrents->at(index).handle.set_download_limit(speed); - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_get_per_download_rate_limit(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_get_per_download_rate_limit()" << std::endl; -#endif - python_long unique_ID; - - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - if (M_torrents->at(index).handle.is_valid()) - return Py_BuildValue("i", (python_long)M_torrents->at(index).handle.download_limit()); - else - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_set_listen_on(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_listen_on()" << std::endl; -#endif - PyObject *port_vec; - if (!PyArg_ParseTuple(args, "O", &port_vec)) - return NULL; - - try { - M_ses->listen_on(std::make_pair( PyInt_AsLong(PyList_GetItem(port_vec, 0)), - PyInt_AsLong(PyList_GetItem(port_vec, 1))), ""); - } - catch (...) { - //Can't listen on that port, so lets try a range of 40000-60000 - M_ses->listen_on(std::make_pair(40000, 60000), ""); - } - - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_is_listening(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_is_listening()" << std::endl; -#endif - long ret = (M_ses->is_listening() != 0); - - return Py_BuildValue("i", ret); -} - - -static PyObject *torrent_listening_port(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_listening_port()" << std::endl; -#endif - return Py_BuildValue("i", (python_long)M_ses->listen_port()); -} - - -static PyObject *torrent_set_max_upload_slots_global(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_max_upload_slots_global()" << std::endl; -#endif - python_long max_up; - if (!PyArg_ParseTuple(args, "i", &max_up)) - return NULL; - - M_ses->set_max_uploads(max_up); - - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_set_max_connections_global(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_max_connections_global()" << std::endl; -#endif - python_long max_conn; - if (!PyArg_ParseTuple(args, "i", &max_conn)) - return NULL; - - // printf("Setting max connections: %d\r\n", max_conn); - M_ses->set_max_connections(max_conn); - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_dump_file_info(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_dump_file_info()" << std::endl; -#endif - const char *name; - if (!PyArg_ParseTuple(args, "s", &name)) - return NULL; - - try{ - torrent_info t = internal_get_torrent_info(name); - - PyObject *file_info; - long file_index = 0; - PyObject *ret = PyTuple_New(t.num_files()); - - for(torrent_info::file_iterator i = t.begin_files(); i != t.end_files(); ++i) - { - file_entry const &currFile = (*i); - - file_info = Py_BuildValue( - "{s:s,s:L}", - "path", currFile.path.string().c_str(), - "size", currFile.size - ); - - PyTuple_SetItem(ret, file_index, file_info); - file_index++; - }; - - return ret; - } - catch(invalid_torrent_file&){ - return NULL; - } - catch(invalid_encoding&){ - return NULL; - } -} - -static PyObject *torrent_dump_trackers(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_dump_trackers()" << std::endl; -#endif - const char *name; - if (!PyArg_ParseTuple(args, "s", &name)) - return NULL; - - torrent_info t = internal_get_torrent_info(name); - std::string trackerslist; - { - for (std::vector::const_iterator i = t.trackers().begin(); - i != t.trackers().end(); ++i) - { - trackerslist = trackerslist + i->url +"\n"; - } - } - return Py_BuildValue("s",trackerslist.c_str()); -} - -static PyObject *torrent_add_torrent(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_add_torrent()" << std::endl; -#endif - const char *name, *save_dir; - python_long compact; - if (!PyArg_ParseTuple(args, "ssi", &name, &save_dir, &compact)) - return NULL; - - boost::filesystem::path save_dir_2 (save_dir, empty_name_check); - try - { - long ret = internal_add_torrent(name, compact, save_dir_2); - if (PyErr_Occurred()) - return NULL; - else - return Py_BuildValue("i", ret); - } - catch (invalid_encoding&) - { RAISE_PTR(InvalidEncodingError, ""); } - catch (invalid_handle&) - { printf("invalid handle error on add_torrent"); } - catch (invalid_torrent_file&) - { RAISE_PTR(InvalidTorrentError, ""); } - catch (boost::filesystem::filesystem_error&) - { RAISE_PTR(FilesystemError, ""); } - catch (duplicate_torrent&) - { RAISE_PTR(DuplicateTorrentError, "libtorrent reports this is a duplicate torrent"); } -} - -static PyObject *torrent_test_duplicate(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_test_duplicate()" << std::endl; -#endif - const char *name; - python_long unique_ID; - if (!PyArg_ParseTuple(args, "si", &name, &unique_ID)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_info t = internal_get_torrent_info(name); - return Py_BuildValue("b", t.info_hash() == M_torrents->at(index).handle.info_hash()); - -} - -static PyObject *torrent_move_storage(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_move_storage()" << std::endl; -#endif - const char *move_dir; - python_long unique_ID; - if (!PyArg_ParseTuple(args, "is", &unique_ID, &move_dir)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - boost::filesystem::path move_dir_2 (move_dir, empty_name_check); - if (M_torrents->at(index).handle.is_valid()) - M_torrents->at(index).handle.move_storage(move_dir_2); - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_remove_torrent(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_remove_torrent()" << std::endl; -#endif - python_long unique_ID, delete_files; - if (!PyArg_ParseTuple(args, "ii", &unique_ID, &delete_files)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - internal_remove_torrent(index, delete_files); - - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_get_num_torrents(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_get_num_torrents()" << std::endl; -#endif - return Py_BuildValue("i", M_torrents->size()); -} - - -static PyObject *torrent_reannounce(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_reannounce()" << std::endl; -#endif - python_long unique_ID; - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - M_torrents->at(index).handle.force_reannounce(); - - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_pause(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_pause()" << std::endl; -#endif - python_long unique_ID; - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - - try { - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - torrent_handle& h = M_torrents->at(index).handle; - if (h.is_valid()){ - h.pause(); - } - - } - catch (invalid_handle&){ - printf("invalid handle. something bad happened in libtorrent\n"); - } - catch (...){} - - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_resume(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_resume()" << std::endl; -#endif - python_long unique_ID; - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - - try { - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - torrent_handle& h = M_torrents->at(index).handle; - if (h.is_valid()){ - h.resume(); - } - - } - catch (invalid_handle&){ - printf("invalid handle. something bad happened in libtorrent\n"); - } - catch (...){} - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_has_piece(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_has_piece()" << std::endl; -#endif - python_long unique_ID; - long piece_index; - bool has_piece; - if (!PyArg_ParseTuple(args, "ii", &unique_ID, &piece_index)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_status s = M_torrents->at(index).handle.status(); - if (s.pieces == 0) - return Py_BuildValue("b", false); - has_piece = internal_has_piece(*s.pieces, piece_index); - return Py_BuildValue("b", has_piece); -} - -static PyObject *torrent_get_all_piece_info(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_get_all_piece_info()" << std::endl; -#endif - python_long unique_ID; - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_handle h = M_torrents->at(index).handle; - std::vector queue; - std::vector& q = queue; - h.get_download_queue(q); - PyObject *piece_info; - long piece_index = 0; - PyObject *ret = PyTuple_New(q.size()); - - for(unsigned long i=0; iat(index).handle; - partial_piece_info piece_info = internal_get_piece_info(h, piece_index); - int blocks_total=0, blocks_finished=0; - if(piece_info.piece_index == piece_index) - { - blocks_total = piece_info.blocks_in_piece; - blocks_finished = piece_info.finished; - } - return Py_BuildValue("{s:i,s:i}", - "blocks_total", blocks_total, - "blocks_finished", blocks_finished); -} - -static PyObject *torrent_get_torrent_state(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_get_torrent_state()" << std::endl; -#endif - python_long unique_ID; - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_t &t = M_torrents->at(index); - torrent_status s = t.handle.status(); - const torrent_info &i = t.handle.get_torrent_info(); - - long connected_seeds = 0; - long connected_peers = 0; - long total_seeds = 0; - long total_peers = 0; - - connected_peers = s.num_peers - s.num_seeds; - connected_seeds = s.num_seeds; - - total_seeds = s.num_complete != -1? s.num_complete : connected_seeds; - total_peers = s.num_incomplete != -1? s.num_incomplete : connected_peers; - - // The following section computes the ranges of pieces that have been downloaded - std::vector downloaded_range; - bool range_opened = false; - for (unsigned int i=0; i <= s.pieces->size(); ++i) { - bool downloaded = (isize() && s.pieces->at(i)); - if (!range_opened) { - if (downloaded) { - range_opened = true; - downloaded_range.push_back(i); - } - } else { - if (!downloaded) { - range_opened = false; - downloaded_range.push_back(i-1); - } - } - } - PyObject *pieces_range = PyTuple_New(downloaded_range.size() / 2); - for(unsigned long i=0; i < downloaded_range.size(); i+=2) { - PyObject *rangepos; - rangepos = Py_BuildValue("[i,i]", downloaded_range[i], - downloaded_range[i+1]); - PyTuple_SetItem(pieces_range, i/2, rangepos); - } - - PyObject *ret = Py_BuildValue("{s:s,s:i,s:i,s:l,s:l,s:f,s:f,s:b,s:f,s:L,s:L,s:s,s:s,s:f,s:L,s:L,s:O,s:i,s:i,s:L,s:i,s:i,s:l,s:l,s:b,s:b,s:L,s:L,s:L,s:b}", - "name", t.handle.get_torrent_info().name().c_str(), - "num_files", t.handle.get_torrent_info().num_files(), - "state", s.state, - "num_peers", connected_peers, - "num_seeds", connected_seeds, - "distributed_copies", s.distributed_copies == -1.0 ? 0.0 : s.distributed_copies, - "download_rate", s.download_payload_rate, - "storage_mode", s.storage_mode, - "upload_rate", s.upload_payload_rate, - "total_download", s.total_download, - "total_upload", s.total_upload, - "next_announce", boost::posix_time::to_simple_string(s.next_announce).c_str(), - "tracker", s.current_tracker.c_str(), - "progress", s.progress, - "total_payload_download", s.total_payload_download, - "total_payload_upload", s.total_payload_upload, - "pieces", pieces_range, - "pieces_done", s.num_pieces, - "block_size", s.block_size, - "total_size", i.total_size(), - "piece_length", i.piece_length(), - "num_pieces", i.num_pieces(), - "total_peers", total_peers, - "total_seeds", total_seeds, - "is_paused", t.handle.is_paused(), - "is_seed", t.handle.is_seed(), - "total_done", s.total_done, - "total_wanted", s.total_wanted, - "total_wanted_done", s.total_wanted_done, - "is_finished", t.handle.is_finished()); - - Py_DECREF(pieces_range); - return ret; -}; - -static PyObject *torrent_pop_event(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_pop_event()" << std::endl; -#endif - std::auto_ptr a; - - a = M_ses->pop_alert(); - - alert *popped_alert = a.get(); - - if (!popped_alert) - { - Py_INCREF(Py_None); return Py_None; - } else if (dynamic_cast(popped_alert)) - { - std::string peer_IP = - (dynamic_cast(popped_alert))->ip.to_string(); - return Py_BuildValue("{s:i,s:s,s:s}", - "event_type", EVENT_PEER_BLOCKED, - "ip", peer_IP.c_str(), - "message", a->msg().c_str()); - } else if (dynamic_cast(popped_alert)) - { - return Py_BuildValue("{s:i,s:s}", - "event_type", EVENT_LISTEN_FAILED, - "message", a->msg().c_str()); - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - int piece_index = (dynamic_cast(popped_alert))->piece_index; - int block_index = (dynamic_cast(popped_alert))->block_index; - std::string speedmsg = (dynamic_cast(popped_alert))->peer_speedmsg; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:i,s:i,s:s,s:s}", - "event_type", EVENT_BLOCK_DOWNLOADING, - "unique_ID", M_torrents->at(index).unique_ID, - "block_index", block_index, - "piece_index", piece_index, - "peer_speed", speedmsg.c_str(), - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - int piece_index = (dynamic_cast(popped_alert))->piece_index; - int block_index = (dynamic_cast(popped_alert))->block_index; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:i,s:i,s:s}", - "event_type", EVENT_BLOCK_FINISHED, - "unique_ID", M_torrents->at(index).unique_ID, - "block_index", block_index, - "piece_index", piece_index, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - int piece_index = (dynamic_cast(popped_alert))->piece_index; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:i,s:s}", - "event_type", EVENT_PIECE_FINISHED, - "unique_ID", M_torrents->at(index).unique_ID, - "piece_index", piece_index, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:s}", - "event_type", EVENT_FINISHED, - "unique_ID", M_torrents->at(index).unique_ID, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - peer_id peer_ID = (dynamic_cast(popped_alert))->pid; - std::string peer_IP = - (dynamic_cast(popped_alert))->ip.address().to_string(); - - return Py_BuildValue("{s:i,s:s,s:s,s:s}", "event_type", EVENT_PEER_ERROR, - "client_ID", identify_client(peer_ID).c_str(), - "ip", peer_IP.c_str(), - "message", a->msg().c_str()); - } else if (dynamic_cast(popped_alert)) - { - peer_id peer_ID = (dynamic_cast(popped_alert))->pid; - - return Py_BuildValue("{s:i,s:s,s:s}", - "event_type", EVENT_INVALID_REQUEST, - "client_ID", identify_client(peer_ID).c_str(), - "message", a->msg().c_str()); - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:s}", - "event_type", EVENT_FILE_ERROR, - "unique_ID", M_torrents->at(index).unique_ID, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:i,s:s}", - "event_type", EVENT_HASH_FAILED_ERROR, - "unique_ID", M_torrents->at(index).unique_ID, - "piece_index", - long((dynamic_cast(popped_alert))->piece_index), - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - std::string peer_IP = (dynamic_cast(popped_alert))->ip.address().to_string(); - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:s,s:s}", - "event_type", EVENT_PEER_BAN_ERROR, - "unique_ID", M_torrents->at(index).unique_ID, - "ip", peer_IP.c_str(), - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:s}", - "event_type", EVENT_FASTRESUME_REJECTED_ERROR, - "unique_ID", M_torrents->at(index).unique_ID, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:s}", - "event_type", EVENT_TRACKER_ANNOUNCE, - "unique_ID", - M_torrents->at(index).unique_ID, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - int status_code = (dynamic_cast(popped_alert))->status_code; - int times_in_row = (dynamic_cast(popped_alert))->times_in_row; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:i,s:i,s:s}", - "event_type", EVENT_TRACKER_ALERT, - "unique_ID", - M_torrents->at(index).unique_ID, - "status_code", status_code, - "times_in_row", times_in_row, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:s}", - "event_type", EVENT_STORAGE_MOVED, - "unique_ID", M_torrents->at(index).unique_ID, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:i,s:i,s:s}", - "event_type", EVENT_TRACKER_REPLY, - "unique_ID", M_torrents->at(index).unique_ID, - "num_complete", handle.status().num_complete, - "num_incomplete", handle.status().num_incomplete, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:s}", - "event_type", EVENT_TRACKER_WARNING, - "unique_ID", - M_torrents->at(index).unique_ID, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:s}", - "event_type", EVENT_FINISHED_CHECKING, - "unique_ID", M_torrents->at(index).unique_ID, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } else if (dynamic_cast(popped_alert)) - { - torrent_handle handle = (dynamic_cast(popped_alert))->handle; - - long index = get_torrent_index(handle); - if (PyErr_Occurred()) - return NULL; - - if (handle_exists(handle)) - return Py_BuildValue("{s:i,s:i,s:s}", - "event_type", EVENT_TORRENT_PAUSED, - "unique_ID", M_torrents->at(index).unique_ID, - "message", a->msg().c_str()); - else - { Py_INCREF(Py_None); return Py_None; } - } - return Py_BuildValue("{s:i,s:s}", "event_type", EVENT_OTHER, - "message", a->msg().c_str() ); -} - - -static PyObject *torrent_get_session_info(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_get_session_info()" << std::endl; -#endif - session_status s = M_ses->status(); - - return Py_BuildValue("{s:l,s:f,s:f,s:ls:l,s:f,s:f}", - "has_incoming_connections", long(s.has_incoming_connections), - "upload_rate", float(s.payload_upload_rate), - "download_rate", float(s.payload_download_rate), - "num_peers", long(s.num_peers), - "num_connections", long(M_ses->num_connections()), - "total_downloaded", float(s.total_payload_download), - "total_uploaded", float(s.total_payload_upload)); -} - - -static PyObject *torrent_get_peer_info(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_get_peer_info()" << std::endl; -#endif - python_long unique_ID; - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - std::vector peers; - M_torrents->at(index).handle.get_peer_info(peers); - - PyObject *peer_info; - PyObject *ret = PyTuple_New(peers.size()); - PyObject *curr_piece, *py_pieces; - - for (unsigned long i = 0; i < peers.size(); i++) - { - std::vector &pieces = peers[i].pieces; - unsigned long pieces_had = 0; - - py_pieces = PyTuple_New(pieces.size()); - - for (unsigned long piece = 0; piece < pieces.size(); piece++) - { - if (pieces[piece]) - pieces_had++; - - curr_piece = Py_BuildValue("i", long(pieces[piece])); - PyTuple_SetItem(py_pieces, piece, curr_piece); - } - - std::stringstream country; - country << peers[i].country[0] << peers[i].country[1]; - - peer_info = Py_BuildValue( - "{s:f,s:L,s:f,s:L,s:i,s:i,s:b,s:b,s:b,s:b,s:b,s:b,s:b,s:b,s:b,s:s,s:b,s:s,s:f,s:O,s:b,s:b,s:s}", - "download_speed", peers[i].down_speed, - "total_download", peers[i].total_download, - "upload_speed", peers[i].up_speed, - "total_upload", peers[i].total_upload, - "download_queue_length", peers[i].download_queue_length, - "upload_queue_length", peers[i].upload_queue_length, - "is_interesting", ((peers[i].flags & peer_info::interesting) != 0), - "is_choked", ((peers[i].flags & peer_info::choked) != 0), - "is_remote_interested", ((peers[i].flags & peer_info::remote_interested) != 0), - "is_remote_choked", ((peers[i].flags & peer_info::remote_choked) != 0), - "supports_extensions", ((peers[i].flags & peer_info::supports_extensions) != 0), - "is_local_connection", ((peers[i].flags & peer_info::local_connection) != 0), - "is_awaiting_handshake", ((peers[i].flags & peer_info::handshake) != 0), - "is_connecting", ((peers[i].flags & peer_info::connecting) != 0), - "is_queued", ((peers[i].flags & peer_info::queued) != 0), - "client", peers[i].client.c_str(), - "is_seed", ((peers[i].flags & peer_info::seed) != 0), - "ip", peers[i].ip.address().to_string().c_str(), - "peer_has", float(float(pieces_had)*100.0/pieces.size()), - "pieces", py_pieces, - "rc4_encrypted", ((peers[i].flags & peer_info::rc4_encrypted) != 0), - "plaintext_encrypted", ((peers[i].flags & peer_info::plaintext_encrypted) != 0), - "country", country.str().c_str() - ); - - Py_DECREF(py_pieces); // Assuming the previous line does NOT steal the ref, then this is - // needed! - - PyTuple_SetItem(ret, i, peer_info); - }; - - return ret; -}; - -static PyObject *torrent_get_file_info(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_get_file_info()" << std::endl; -#endif - python_long unique_ID; - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - std::vector temp_files; - - PyObject *file_info; - - std::vector progresses; - - torrent_t &t = M_torrents->at(index); - t.handle.file_progress(progresses); - - torrent_info::file_iterator start = - t.handle.get_torrent_info().begin_files(); - torrent_info::file_iterator end = - t.handle.get_torrent_info().end_files(); - - long fileIndex = 0; - - for(torrent_info::file_iterator i = start; i != end; ++i) - { - file_entry const &currFile = (*i); - - file_info = Py_BuildValue( - "{s:s,s:L,s:f}", - "path", currFile.path.string().c_str(), - "size", currFile.size, - "progress", progresses[i - start]*100.0 - ); - - fileIndex++; - - temp_files.push_back(file_info); - }; - - PyObject *ret = PyTuple_New(temp_files.size()); - - for (unsigned long i = 0; i < temp_files.size(); i++) - PyTuple_SetItem(ret, i, temp_files[i]); - - return ret; -}; - -static PyObject *torrent_get_file_piece_range(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_get_file_piece_range()" << std::endl; -#endif - python_long unique_ID; - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - std::vector temp_files; - - torrent_info const &info = M_torrents->at(index).handle.get_torrent_info(); - int file_index = 0; - size_type first_num_blocks, last_num_blocks; - PyObject *file_info; - - for(torrent_info::file_iterator i = info.begin_files(); i != info.end_files(); ++i) - { - file_entry const &currFile = (*i); - peer_request first_index = info.map_file(file_index, 0, 1); - peer_request last_index = info.map_file(file_index, currFile.size-1, 1); - first_num_blocks = info.piece_length()/(16 * 1024); - last_num_blocks = ceil((double)(info.piece_size(last_index.piece))/(16 * 1024)); - file_info = Py_BuildValue( - "{s:i,s:i,s:i,s:i,s:s}", - "first_index", first_index.piece, - "last_index", last_index.piece, - "first_num_blocks", (int)first_num_blocks, - "last_num_blocks", (int)last_num_blocks, - "path", currFile.path.string().c_str() - ); - file_index++; - temp_files.push_back(file_info); - }; - - PyObject *ret = PyTuple_New(temp_files.size()); - - for (unsigned long i = 0; i < temp_files.size(); i++) - PyTuple_SetItem(ret, i, temp_files[i]); - - return ret; -}; - -static PyObject *torrent_constants(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_constants()" << std::endl; -#endif - Py_INCREF(M_constants); return M_constants; -} - - -static PyObject *torrent_start_DHT(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_start_DHT()" << std::endl; -#endif - const char *DHT_path; - if (!PyArg_ParseTuple(args, "s", &DHT_path)) - return NULL; - - // printf("Loading DHT state from %s\r\n", DHT_path); - - boost::filesystem::path tempPath(DHT_path, empty_name_check); - boost::filesystem::ifstream DHT_state_file(tempPath, std::ios_base::binary); - DHT_state_file.unsetf(std::ios_base::skipws); - - entry DHT_state; - try - { - DHT_state = bdecode(std::istream_iterator(DHT_state_file), - std::istream_iterator()); - M_ses->start_dht(DHT_state); - // printf("DHT state recovered.\r\n"); - - // // Print out the state data from the FILE (not the session!) - // printf("Number of DHT peers in recovered state: %ld\r\n", count_DHT_peers(DHT_state)); - - } - catch (std::exception&) - { - printf("No DHT file to resume\r\n"); - M_ses->start_dht(); - } - - M_ses->add_dht_router(std::make_pair(std::string("router.bittorrent.com"), - DHT_ROUTER_PORT)); - M_ses->add_dht_router(std::make_pair(std::string("router.utorrent.com"), - DHT_ROUTER_PORT)); - M_ses->add_dht_router(std::make_pair(std::string("router.bitcomet.com"), - DHT_ROUTER_PORT)); - - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_stop_DHT(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_stop_DHT()" << std::endl; -#endif - const char *DHT_path; - if (!PyArg_ParseTuple(args, "s", &DHT_path)) - return NULL; - - // printf("Saving DHT state to %s\r\n", DHT_path); - - boost::filesystem::path tempPath = boost::filesystem::path(DHT_path, empty_name_check); - - try - { - entry DHT_state = M_ses->dht_state(); - - // printf("Number of DHT peers in state, saving: %ld\r\n", count_DHT_peers(DHT_state)); - - boost::filesystem::ofstream out(tempPath, std::ios_base::binary); - out.unsetf(std::ios_base::skipws); - bencode(std::ostream_iterator(out), DHT_state); - } - catch (std::exception& e) - { - printf("An error occured in saving DHT\r\n"); - std::cerr << e.what() << "\n"; - } - - M_ses->stop_dht(); - - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_get_DHT_info(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_get_DHT_info()" << std::endl; -#endif - entry DHT_state = M_ses->dht_state(); - - return Py_BuildValue("l", python_long(count_DHT_peers(DHT_state))); -} - - -static PyObject *torrent_create_torrent(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_create_torrent()" << std::endl; -#endif - using namespace libtorrent; - using namespace boost::filesystem; - - //path::default_name_check(no_check); - - char *destination, *comment, *creator_str, *input, *trackers, *webseeds; - bool *priv; - python_long piece_size; - if (!PyArg_ParseTuple(args, "ssssisbs", - &destination, &input, &trackers, &comment, &piece_size, &creator_str, &priv, &webseeds)) - return NULL; - - piece_size = piece_size * 1024; - - try - { - boost::intrusive_ptr t(new torrent_info); - boost::filesystem::path full_path = complete(boost::filesystem::path(input)); - boost::filesystem::ofstream out(complete(boost::filesystem::path(destination)), std::ios_base::binary); - - - internal_add_files(*t, full_path.branch_path(), full_path.leaf()); - t->set_piece_size(piece_size); - - file_pool fp; - boost::scoped_ptr st(default_storage_constructor(t, full_path.branch_path(), fp)); - - std::string stdTrackers(trackers); - unsigned long index = 0, next = stdTrackers.find("\n"); - while (1 == 1) - { - t->add_tracker(stdTrackers.substr(index, next-index)); - index = next + 1; - if (next >= stdTrackers.length()) - break; - next = stdTrackers.find("\n", index); - if (next == std::string::npos) - break; - } - - std::string stdWebseeds(webseeds); - unsigned long index2 = 0, next2 = stdWebseeds.find("\n"); - while (1 == 1) - { - t->add_url_seed(stdWebseeds.substr(index2, next2-index)); - index2 = next2 + 1; - if (next2 >= stdWebseeds.length()) - break; - next2 = stdWebseeds.find("\n", index2); - if (next2 == std::string::npos) - break; - } - - int num = t->num_pieces(); - std::vector buf(piece_size); - for (int i = 0; i < num; ++i) - { - st->read(&buf[0], i, 0, t->piece_size(i)); - hasher h(&buf[0], t->piece_size(i)); - t->set_hash(i, h.final()); - } - - t->set_creator(creator_str); - t->set_comment(comment); - t->set_priv(priv); - entry e = t->create_torrent(); - bencode(std::ostream_iterator(out), e); - return Py_BuildValue("l", 1); - } catch (std::exception& e) - { - // std::cerr << e.what() << "\n"; - // return Py_BuildValue("l", 0); - RAISE_PTR(DelugeError, e.what()); - return Py_BuildValue("l", 0); - } -} - - -static PyObject *torrent_reset_IP_filter(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_reset_IP_filter()" << std::endl; -#endif - // Remove existing filter, if there is one - if (M_the_filter != NULL) - delete M_the_filter; - - M_the_filter = new ip_filter(); - - M_ses->set_ip_filter(*M_the_filter); - - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_add_range_to_IP_filter(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_add_range_to_IP_filter()" << std::endl; -#endif - if (M_the_filter == NULL) { - RAISE_PTR(DelugeError, "No filter defined, use reset_IP_filter"); - } - - char *start, *end; - if (!PyArg_ParseTuple(args, "ss", &start, &end)) - return NULL; - - address_v4 inet_start = address_v4::from_string(start); - address_v4 inet_end = address_v4::from_string(end); - M_the_filter->add_rule(inet_start, inet_end, ip_filter::blocked); - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_set_IP_filter(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_IP_filter()" << std::endl; -#endif - if (M_the_filter == NULL) { - RAISE_PTR(DelugeError, "No filter defined, use reset_IP_filter"); - } - M_ses->set_ip_filter(*M_the_filter); - - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_use_upnp(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_use_upnp()" << std::endl; -#endif - python_long action; - PyArg_ParseTuple(args, "i", &action); - - if (action){ - M_ses->start_upnp(); - } - else{ - M_ses->stop_upnp(); - } - - Py_INCREF(Py_None); return Py_None; - -} - -static PyObject *torrent_use_lsd(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_use_lsd()" << std::endl; -#endif - python_long action; - PyArg_ParseTuple(args, "i", &action); - - if (action){ - M_ses->start_lsd(); - } - else{ - M_ses->stop_lsd(); - } - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_send_redund(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_send_redund()" << std::endl; -#endif - python_long action; - PyArg_ParseTuple(args, "i", &action); - - M_settings->send_redundant_have = action; - M_ses->set_settings(*M_settings); - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_use_natpmp(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_use_natpmp()" << std::endl; -#endif - python_long action; - - PyArg_ParseTuple(args, "i", &action); - - if (action){ - M_ses->start_natpmp(); - } - else{ - M_ses->stop_natpmp(); - } - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_use_utpex(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_use_utpex()" << std::endl; -#endif - python_long action; - - PyArg_ParseTuple(args, "i", &action); - - if (action){ - M_ses->add_extension(&libtorrent::create_ut_pex_plugin); - } - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_pe_settings(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_pe_settings()" << std::endl; -#endif - M_pe_settings = new pe_settings(); - libtorrent::pe_settings::enc_policy out, in, prefer; - libtorrent::pe_settings::enc_level level; - - PyArg_ParseTuple(args, "iiii", &out, &in, &level, &prefer); - - M_pe_settings->out_enc_policy = out; - M_pe_settings->in_enc_policy = in; - M_pe_settings->allowed_enc_level = level; - M_pe_settings->prefer_rc4 = prefer; - - M_ses->set_pe_settings(*M_pe_settings); - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_set_ratio(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_ratio()" << std::endl; -#endif - python_long unique_ID; - float num; - if (!PyArg_ParseTuple(args, "if", &unique_ID, &num)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - M_torrents->at(index).handle.set_ratio(num); - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_proxy_settings(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_proxy_settings()" << std::endl; -#endif - char *server, *login, *pasw; - int portnum; - libtorrent::proxy_settings::proxy_type proxytype; - char *dtpwproxy; - - PyArg_ParseTuple(args, "sssiis", &server, &login, &pasw, &portnum, - &proxytype, &dtpwproxy); - - M_proxy_settings = new proxy_settings(); - M_proxy_settings->type = proxytype; - M_proxy_settings->username = login; - M_proxy_settings->password = pasw; - M_proxy_settings->hostname = server; - M_proxy_settings->port = portnum; - - if (strcmp(dtpwproxy, "peer") == 0) { - M_ses->set_peer_proxy(*M_proxy_settings); - } - - if (strcmp(dtpwproxy, "tracker") == 0) { - M_ses->set_tracker_proxy(*M_proxy_settings); - } - - if (strcmp(dtpwproxy, "dht") == 0) { - M_ses->set_dht_proxy(*M_proxy_settings); - } - if (strcmp(dtpwproxy, "web") == 0) { - M_ses->set_web_seed_proxy(*M_proxy_settings); - } - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_get_trackers(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_get_trackers()" << std::endl; -#endif - python_long unique_ID; - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - try { - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_handle& h = M_torrents->at(index).handle; - std::string trackerslist; - if (h.is_valid() && h.has_metadata()) - { - for (std::vector::const_iterator i = h.trackers().begin(); - i != h.trackers().end(); ++i) - { - trackerslist = trackerslist + i->url +"\n"; - } - return Py_BuildValue("s",trackerslist.c_str()); - } - else{ - Py_INCREF(Py_None); return Py_None; - } - } - catch (...){ - printf("error getting trackers, probably invalid handle\n"); - Py_INCREF(Py_None); return Py_None; - } -} - -static PyObject *torrent_replace_trackers(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_replace_trackers()" << std::endl; -#endif - python_long unique_ID; - const char* tracker; - if (!PyArg_ParseTuple(args, "iz", &unique_ID, &tracker)) - return NULL; - - try { - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - if (M_torrents->at(index).handle.is_valid()){ - std::vector trackerlist; - std::istringstream trackers(tracker); - std::string line; - while (std::getline(trackers, line)) { - libtorrent::announce_entry a_entry(line); - trackerlist.push_back(a_entry); - } - if (trackerlist.empty()){ - std::vector empty; - M_torrents->at(index).handle.replace_trackers(empty); - } - else{ - M_torrents->at(index).handle.replace_trackers(trackerlist); - M_torrents->at(index).handle.force_reannounce(); - } - } - } - catch (invalid_handle&) - { - printf("invalid handle. something bad happened in libtorrent\n"); - } - catch (...) {} - Py_INCREF(Py_None); return Py_None; -} -static PyObject *torrent_prioritize_files(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_prioritize_files()" << std::endl; -#endif - python_long unique_ID; - PyObject *priorities_list_object; - - if (!PyArg_ParseTuple(args, "iO", &unique_ID, &priorities_list_object)) - return NULL; - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_t &t = M_torrents->at(index); - int num_files = t.handle.get_torrent_info().num_files(); - assert(PyList_Size(priorities_list_object) == num_files); - - std::vector priorities_vector(num_files); - - for (long i = 0; i < num_files; i++) { - priorities_vector.at(i) = - PyInt_AsLong(PyList_GetItem(priorities_list_object, i)); - } - - t.handle.prioritize_files(priorities_vector); - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_prioritize_first_last_pieces(PyObject *self, - PyObject *args) -{ -#define FIRST_LAST_PRIO 6 -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_prioritize_first_last_pieces()" << std::endl; -#endif - - // Prioritize first and last 1% of file size bytes in each file of torrent - // with unique_ID - python_long unique_ID; - PyObject *priorities_list_object; - - // We need priorities_list_object to see whether file is marked to - // download(has priority > 0) or not. - if (!PyArg_ParseTuple(args, "iO", &unique_ID, &priorities_list_object)) - return NULL; - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_t &t = M_torrents->at(index); - const torrent_info &tor_info = t.handle.get_torrent_info(); - int num_files = tor_info.num_files(); - assert(PyList_Size(priorities_list_object) == num_files); - int num_pieces = tor_info.num_pieces(); - - std::vector priorities_vector(num_pieces); - priorities_vector = t.handle.piece_priorities(); - - for (long i = 0; i < num_files; i++) { - file_entry const &file = tor_info.file_at(i); - if(file.size == 0) { - continue; - } - - // Check if file has priority 0 - means don't download - skip it - // and move to next file - int file_prio = PyInt_AsLong(PyList_GetItem(priorities_list_object, - i)); - if(file_prio == 0) { - continue; - } - - int start_piece = tor_info.map_file(i, 0, 0).piece; - int end_piece = tor_info.map_file(i, file.size, 0).piece; - if (end_piece == num_pieces) - end_piece -= 1; - // Set prio_size to 1% of the file size - size_type prio_size = file.size / 100; - int prio_pieces = tor_info.map_file(i, prio_size, 0).piece - - start_piece + 1; - - for (int piece = 0; piece < prio_pieces; piece++) { - priorities_vector.at(start_piece + piece) = FIRST_LAST_PRIO; - priorities_vector.at(end_piece - piece) = FIRST_LAST_PRIO; - } - } - - t.handle.prioritize_pieces(priorities_vector); - - #ifndef NDEBUG - std::cout << "after prioritization\n"; - for (long i = 0; i < num_pieces; i++) { - std::cout << priorities_vector.at(i); - } - std::cout << "\n"; - #endif - - Py_INCREF(Py_None); return Py_None; -} - - -static PyObject *torrent_set_priv(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_priv()" << std::endl; -#endif - using namespace libtorrent; - python_long unique_ID; - bool onoff; - - if (!PyArg_ParseTuple(args, "ib", &unique_ID, &onoff)) - return NULL; - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_t &t = M_torrents->at(index); - torrent_info info = t.handle.get_torrent_info(); - - info.set_priv(onoff); - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_set_max_connections_per_torrent(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_max_connections_per_torrent()" << std::endl; -#endif - python_long unique_ID, max_connections; - - if (!PyArg_ParseTuple(args, "ii", &unique_ID, &max_connections)) - return NULL; - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_t &t = M_torrents->at(index); - t.handle.set_max_connections(max_connections); - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_set_max_upload_slots_per_torrent(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_set_max_upload_slots_per_torrent()" << std::endl; -#endif - python_long unique_ID, max_upload_slots; - - if (!PyArg_ParseTuple(args, "ii", &unique_ID, &max_upload_slots)) - return NULL; - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_t &t = M_torrents->at(index); - t.handle.set_max_uploads(max_upload_slots); - - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_add_url_seed(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_add_url_seed()" << std::endl; -#endif - python_long unique_ID; - char *address; - - if (!PyArg_ParseTuple(args, "is", &unique_ID, &address)) - return NULL; - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_t &t = M_torrents->at(index); - t.handle.add_url_seed(address); - Py_INCREF(Py_None); return Py_None; -} - -static PyObject *torrent_scrape_tracker(PyObject *self, PyObject *args) -{ -#ifdef DELUGE_CORE_DEBUG -time_t rawtime; -struct tm *timeinfo; -time(&rawtime); -timeinfo = localtime(&rawtime); -std::cout << asctime(timeinfo) << " torrent_scrape_tracker()" << std::endl; -#endif - python_long unique_ID; - if (!PyArg_ParseTuple(args, "i", &unique_ID)) - return NULL; - - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - torrent_handle& h = M_torrents->at(index).handle; - // For valid torrents, save fastresume data - if (h.is_valid()) - { - h.scrape_tracker(); - } - Py_INCREF(Py_None); return Py_None; -} - -//==================== -// Python Module data -//==================== - -static PyMethodDef deluge_core_methods[] = -{ - {"add_url_seed", torrent_add_url_seed, METH_VARARGS, "."}, - {"pe_settings", torrent_pe_settings, METH_VARARGS, "."}, - {"pre_init", torrent_pre_init, METH_VARARGS, "."}, - {"init", torrent_init, METH_VARARGS, "."}, - {"quit", torrent_quit, METH_VARARGS, "."}, - {"save_fastresume", torrent_save_fastresume, METH_VARARGS, "."}, - {"set_max_half_open", torrent_set_max_half_open, METH_VARARGS, "."}, - {"connection_speed", torrent_connection_speed, METH_VARARGS, "."}, - {"set_download_rate_limit", torrent_set_download_rate_limit, METH_VARARGS, "."}, - {"set_upload_rate_limit", torrent_set_upload_rate_limit, METH_VARARGS, "."}, - {"set_per_upload_rate_limit", torrent_set_per_upload_rate_limit, METH_VARARGS, "."}, - {"set_per_download_rate_limit", torrent_set_per_download_rate_limit, METH_VARARGS, "."}, - {"get_per_upload_rate_limit", torrent_get_per_upload_rate_limit, METH_VARARGS, "."}, - {"get_per_download_rate_limit", torrent_get_per_download_rate_limit, METH_VARARGS, "."}, - {"set_listen_on", torrent_set_listen_on, METH_VARARGS, "."}, - {"is_listening", torrent_is_listening, METH_VARARGS, "."}, - {"listening_port", torrent_listening_port, METH_VARARGS, "."}, - {"set_max_upload_slots_global", torrent_set_max_upload_slots_global, METH_VARARGS, "."}, - {"set_max_upload_slots_per_torrent",torrent_set_max_upload_slots_per_torrent, METH_VARARGS, "."}, - {"set_max_connections_global", torrent_set_max_connections_global, METH_VARARGS, "."}, - {"set_max_connections_per_torrent", torrent_set_max_connections_per_torrent, METH_VARARGS, "."}, - {"add_torrent", torrent_add_torrent, METH_VARARGS, "."}, - {"move_storage", torrent_move_storage, METH_VARARGS, "."}, - {"remove_torrent", torrent_remove_torrent, METH_VARARGS, "."}, - {"get_num_torrents", torrent_get_num_torrents, METH_VARARGS, "."}, - {"reannounce", torrent_reannounce, METH_VARARGS, "."}, - {"pause", torrent_pause, METH_VARARGS, "."}, - {"resume", torrent_resume, METH_VARARGS, "."}, - {"get_torrent_state", torrent_get_torrent_state, METH_VARARGS, "."}, - {"pop_event", torrent_pop_event, METH_VARARGS, "."}, - {"get_session_info", torrent_get_session_info, METH_VARARGS, "."}, - {"get_peer_info", torrent_get_peer_info, METH_VARARGS, "."}, - {"get_file_info", torrent_get_file_info, METH_VARARGS, "."}, - {"dump_file_info", torrent_dump_file_info, METH_VARARGS, "."}, - {"constants", torrent_constants, METH_VARARGS, "."}, - {"start_DHT", torrent_start_DHT, METH_VARARGS, "."}, - {"stop_DHT", torrent_stop_DHT, METH_VARARGS, "."}, - {"get_DHT_info", torrent_get_DHT_info, METH_VARARGS, "."}, - {"create_torrent", torrent_create_torrent, METH_VARARGS, "."}, - {"reset_IP_filter", torrent_reset_IP_filter, METH_VARARGS, "."}, - {"add_range_to_IP_filter", torrent_add_range_to_IP_filter, METH_VARARGS, "."}, - {"set_IP_filter", torrent_set_IP_filter, METH_VARARGS, "."}, - {"use_upnp", torrent_use_upnp, METH_VARARGS, "."}, - {"use_lsd", torrent_use_lsd, METH_VARARGS, "."}, - {"send_redund", torrent_send_redund, METH_VARARGS, "."}, - {"use_natpmp", torrent_use_natpmp, METH_VARARGS, "."}, - {"use_utpex", torrent_use_utpex, METH_VARARGS, "."}, - {"set_ratio", torrent_set_ratio, METH_VARARGS, "."}, - {"proxy_settings", torrent_proxy_settings, METH_VARARGS, "."}, - {"get_trackers", torrent_get_trackers, METH_VARARGS, "."}, - {"dump_trackers", torrent_dump_trackers, METH_VARARGS, "."}, - {"replace_trackers", torrent_replace_trackers, METH_VARARGS, "."}, - {"prioritize_files", torrent_prioritize_files, METH_VARARGS, "."}, - {"prioritize_first_last_pieces", torrent_prioritize_first_last_pieces, METH_VARARGS, "."}, - {"set_priv", torrent_set_priv, METH_VARARGS, "."}, - {"test_duplicate", torrent_test_duplicate, METH_VARARGS, "."}, - {"has_piece", torrent_has_piece, METH_VARARGS, "."}, - {"get_piece_info", torrent_get_piece_info, METH_VARARGS, "."}, - {"get_all_piece_info", torrent_get_all_piece_info, METH_VARARGS, "."}, - {"get_file_piece_range", torrent_get_file_piece_range, METH_VARARGS, "."}, - {"scrape_tracker", torrent_scrape_tracker, METH_VARARGS, "."}, - {NULL} -}; - -PyMODINIT_FUNC -initdeluge_core(void) -{ - Py_InitModule("deluge_core", deluge_core_methods); -}; diff --git a/src/deluge_stats.py b/src/deluge_stats.py deleted file mode 100644 index 9e9df9e60..000000000 --- a/src/deluge_stats.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (C) 2006 Alon Zakai ('Kripken') -# -# 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 2, 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. - -import time - -# Global variables. Caching of saved data, mostly - -old_peer_info = None -old_peer_info_timestamp = None - -# Swarm speed - try to guess the speed of the entire swarm -# We return #pieces / second. The calling function should convert pieces to KB, if it wants -# Note that we return the delta from the last call. If the client calls too soon, this may -# be too unreliable. But the client can smooth things out, if desired -def calc_swarm_speed(peer_info): - if old_peer_info is not None: - new_pieces = 0 - peers_known = 0 - - # List new peers - new_peer_IPs = {} # ip->peerinfo dict (from the core) - for peer in peer_info: - new_peer_IPs[peer['ip']] = peer - - for new_IP in new_peer_IPs.keys(): - if new_IP in old_peer_IPs.keys(): - # We know this peer from before, see what changed - peers_known = peers_known + 1 - delta = sum(new_peer_IPs[new_IP].pieces) - sum(old_peer_IPs[new_IP].pieces) - - if delta >= 0: - new_pieces = new_pieces + delta - else: - print "Deluge.stat.calc_swarm_speed: Bad Delta: ", delta, old_peer_IPs[new_IP].pieces, new_peer_IPs[new_IP].pieces - - # Calculate final value - time_delta = time.time() - old_peer_info_timestamp - ret = float(new_pieces)/( float(peers_known) * time_delta ) - - # Save info - old_peer_info = peer_info - old_peer_info_timestamp = time.time() - old_peer_IPs = new_peer_IPs - - return ret diff --git a/src/dgtk.py b/src/dgtk.py deleted file mode 100644 index 9b0a8d046..000000000 --- a/src/dgtk.py +++ /dev/null @@ -1,173 +0,0 @@ -# -*- coding: utf-8 -*- -# dgtk.py -# -# Copyright (C) Zach Tibbitts 2006 -# -# 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 2, 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. - -# Similar to common, this contains any common functions -# related to gtk that are needed by the client - -from itertools import izip - -import common -import pygtk -pygtk.require('2.0') -import gtk - -## Cell data functions to pass to add_func_column() - -def cell_data_speed(column, cell, model, iter, data): - speed = model.get_value(iter, data) - if speed<100: speed_str = "" - else: speed_str = common.fspeed(speed) - cell.set_property('text', speed_str) - -def cell_data_size(column, cell, model, iter, data): - size = model.get_value(iter, data) - size_str = common.fsize(size) - cell.set_property('text', size_str) - -## Functions to create columns - -def add_func_column(view, header, func, data, sortid=None, width=None): - column = gtk.TreeViewColumn(header) - render = gtk.CellRendererText() - column.pack_start(render, True) - column.set_cell_data_func(render, func, data) - if sortid is not None: - column.set_clickable(True) - column.set_sort_column_id(sortid) - else: - try: - if len(data) == 1: - column.set_clickable(True) - column.set_sort_column_id(data[0]) - except TypeError: - column.set_clickable(True) - column.set_sort_column_id(data) - column.set_resizable(True) - if width > 0: - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - column.set_fixed_width(width) - column.set_expand(False) - column.set_min_width(10) - column.set_reorderable(True) - view.append_column(column) - return column - - -def add_text_column(view, header, cid, width=None): - render = gtk.CellRendererText() - column = gtk.TreeViewColumn(header, render, text=cid) - column.set_clickable(True) - column.set_sort_column_id(cid) - column.set_resizable(True) - column.set_expand(False) - if width > 0: - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - column.set_fixed_width(width) - column.set_min_width(10) - column.set_reorderable(True) - view.append_column(column) - return column - -def add_progress_column(view, header, pid, mid, width=None): - render = gtk.CellRendererProgress() - column = gtk.TreeViewColumn(header, render, value=pid, text=mid) - column.set_clickable(True) - column.set_sort_column_id(pid) - column.set_resizable(True) - column.set_expand(False) - column.set_min_width(10) - if width > 0: - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - column.set_fixed_width(width) - column.set_reorderable(True) - view.append_column(column) - return column - -def add_toggle_column(view, header, cid, toggled_signal=None, width=None): - render = gtk.CellRendererToggle() - render.set_property('activatable', True) - column = gtk.TreeViewColumn(header, render, active=cid) - column.set_clickable(True) - column.set_resizable(True) - column.set_expand(False) - if width > 0: - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - column.set_fixed_width(width) - column.set_min_width(10) - column.set_reorderable(True) - view.append_column(column) - if toggled_signal is not None: - render.connect("toggled", toggled_signal) - return column - -def add_texticon_column(view, header, icon_col, text_col, width=None): - column = gtk.TreeViewColumn(header) - column.set_clickable(True) - column.set_resizable(True) - column.set_expand(False) - if width > 0: - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - column.set_fixed_width(width) - column.set_min_width(10) - column.set_reorderable(True) - render = gtk.CellRendererPixbuf() - column.pack_start(render, expand=False) - column.add_attribute(render, 'pixbuf', icon_col) - render = gtk.CellRendererText() - column.pack_start(render, expand=True) - column.add_attribute(render, 'text', text_col) - view.append_column(column) - return column - -def update_store(store, iter, cols, new_values): - """gtk.ListStore update function - - Arguments: - store - gtk.ListStore instance - iter - a valid gtk.TreeIter for the row being modified - cols - iterable containing indexes of columns to change - new_values - iterable with new values for specified columns - - Example: - update_store(file_store, iter, (1, 3), ('test.txt', 9940)) - - """ - - old_values = store.get(iter, *cols) - - for col, old_value, new_value in izip(cols, old_values, new_values): - try: - # equality check because formatting and cell renderer functions - # called on self.torrent_model.set_value() are expensive - if old_value != new_value: - store.set_value(iter, col, new_value) - except: - print "ERR", col, type(new_value), new_value diff --git a/src/dialogs.py b/src/dialogs.py deleted file mode 100644 index 53e5d042e..000000000 --- a/src/dialogs.py +++ /dev/null @@ -1,532 +0,0 @@ -# -*- coding: utf-8 -*- -# dialogs.py -# -# Copyright (C) Zach Tibbitts 2006 -# -# 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 2, 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. - -import gtk - -import common -import dgtk -import files -import pref - -PREFS_FILENAME = "prefs.state" - -class PreferencesDlg: - def __init__(self, preferences, active_port, plugins, plugin_tab=False): - self.glade = gtk.glade.XML(common.get_glade_file("preferences_dialog.glade"), domain='deluge') - self.dialog = self.glade.get_widget("pref_dialog") - if plugin_tab: - self.glade.get_widget("notebook").set_current_page(6) - self.dialog.set_position(gtk.WIN_POS_CENTER) - if not common.windows_check(): - self.dialog.set_icon(common.get_logo(18)) - self.glade.signal_autoconnect({ - 'toggle_ui': self.toggle_ui, - 'on_btn_testport_clicked': self.TestPort, - }) - - self.preferences = preferences - self.active_port = str(active_port) - #init plugin info - self.view = self.glade.get_widget("plugin_view") - self.store = gtk.ListStore(str, bool) - self.store.set_sort_column_id(0, gtk.SORT_ASCENDING) - self.view.set_model(self.store) - try: - self.view.get_selection().set_select_function(self.plugin_clicked, full=True) - except TypeError: - self.view.get_selection().set_select_function(self.old_clicked) - name_col = dgtk.add_text_column(self.view, _("Plugin"), 0) - name_col.set_expand(True) - dgtk.add_toggle_column(self.view, _("Enabled"), 1, toggled_signal=self.plugin_toggled) - signals = {'plugin_pref': self.plugin_pref, - 'on_close_clicked': self.close_clicked} - self.glade.signal_autoconnect(signals) - self.plugins = plugins - - def show(self, interface, window): - # Load settings into dialog - try: - self.glade.get_widget("combo_encin").set_active(self.preferences.get("encin_state")) - self.glade.get_widget("combo_encout").set_active(self.preferences.get("encout_state")) - self.glade.get_widget("combo_enclevel").set_active(self.preferences.get("enclevel_type")) - self.glade.get_widget("combo_peer_proxy_type").set_active(self.preferences.get("peer_proxy_type")) - self.glade.get_widget("combo_dht_proxy_type").set_active(self.preferences.get("dht_proxy_type")) - self.glade.get_widget("combo_tracker_proxy_type").set_active(self.preferences.get("tracker_proxy_type")) - self.glade.get_widget("combo_web_proxy_type").set_active(self.preferences.get("web_proxy_type")) - self.glade.get_widget("chk_autoload").set_active(self.preferences.get("autoload")) - self.glade.get_widget("chk_send_info").set_active(self.preferences.get("send_info")) - self.glade.get_widget("chk_pref_rc4").set_active(self.preferences.get("pref_rc4")) - self.glade.get_widget("chk_peer_proxy").set_active(self.preferences.get("peer_proxy")) - self.glade.get_widget("chk_tracker_proxy").set_active(self.preferences.get("tracker_proxy")) - self.glade.get_widget("chk_dht_proxy").set_active(self.preferences.get("dht_proxy")) - self.glade.get_widget("chk_web_proxy").set_active(self.preferences.get("web_proxy")) - self.glade.get_widget("chk_upnp").set_active(self.preferences.get("use_upnp")) - self.glade.get_widget("chk_lsd").set_active(self.preferences.get("use_lsd")) - self.glade.get_widget("chk_send_redund").set_active(self.preferences.get("send_redund")) - self.glade.get_widget("chk_random_port").set_active(self.preferences.get("random_port")) - self.glade.get_widget("chk_natpmp").set_active(self.preferences.get("use_natpmp")) - self.glade.get_widget("chk_utpex").set_active(self.preferences.get("use_utpex")) - self.glade.get_widget("chk_new_releases").set_active(self.preferences.get("new_releases")) - self.glade.get_widget("chk_use_tray").set_active(self.preferences.get("enable_system_tray")) - self.glade.get_widget("chk_min_on_close").set_active(self.preferences.get("close_to_tray")) - self.glade.get_widget("chk_start_in_tray").set_active(self.preferences.get("start_in_tray")) - self.glade.get_widget("chk_lock_tray").set_active(self.preferences.get("lock_tray")) - self.glade.get_widget("txt_tray_passwd").set_text(self.preferences.get("tray_passwd")) - self.glade.get_widget("txt_peer_proxy_hostname").set_text(self.preferences.get("peer_proxy_hostname")) - self.glade.get_widget("txt_peer_proxy_username").set_text(self.preferences.get("peer_proxy_username")) - self.glade.get_widget("txt_peer_proxy_password").set_text(self.preferences.get("peer_proxy_password")) - self.glade.get_widget("txt_tracker_proxy_hostname").set_text(self.preferences.get("tracker_proxy_hostname")) - self.glade.get_widget("txt_tracker_proxy_username").set_text(self.preferences.get("tracker_proxy_username")) - self.glade.get_widget("txt_tracker_proxy_password").set_text(self.preferences.get("tracker_proxy_password")) - self.glade.get_widget("txt_dht_proxy_hostname").set_text(self.preferences.get("dht_proxy_hostname")) - self.glade.get_widget("txt_dht_proxy_username").set_text(self.preferences.get("dht_proxy_username")) - self.glade.get_widget("txt_dht_proxy_password").set_text(self.preferences.get("dht_proxy_password")) - self.glade.get_widget("txt_web_proxy_hostname").set_text(self.preferences.get("web_proxy_hostname")) - self.glade.get_widget("txt_web_proxy_username").set_text(self.preferences.get("web_proxy_username")) - self.glade.get_widget("txt_web_proxy_password").set_text(self.preferences.get("web_proxy_password")) - self.glade.get_widget("autoload_path_button").set_current_folder(self.preferences.get("default_autoload_path")) - self.glade.get_widget("download_path_button").set_current_folder(self.preferences.get("default_download_path")) - self.glade.get_widget("torrent_path_button").set_current_folder(self.preferences.get("default_torrent_path")) - self.glade.get_widget("chk_enable_files_dialog").set_active(self.preferences.get("enable_files_dialog")) - self.glade.get_widget("chk_enable_multi_only").set_active(self.preferences.get("enable_multi_only")) - self.glade.get_widget("chk_prioritize_first_last_pieces").set_active(self.preferences.get("prioritize_first_last_pieces")) - self.glade.get_widget("radio_compact_allocation").set_active(self.preferences.get("use_compact_storage")) - self.glade.get_widget("radio_full_allocation").set_active(not self.preferences.get("use_compact_storage")) - self.glade.get_widget("active_port_label").set_text(str(self.active_port)) - self.glade.get_widget("spin_port_min").set_value(self.preferences.get("listen_on")[0]) - self.glade.get_widget("spin_port_max").set_value(self.preferences.get("listen_on")[1]) - self.glade.get_widget("spin_max_upload").set_value(self.preferences.get("max_upload_speed")) - self.glade.get_widget("spin_max_upload_slots_global").set_value(float(self.preferences.get("max_upload_slots_global"))) - self.glade.get_widget("spin_max_upload_slots_per_torrent").set_value(float(self.preferences.get("max_upload_slots_per_torrent"))) - self.glade.get_widget("spin_max_download").set_value(self.preferences.get("max_download_speed")) - self.glade.get_widget("spin_max_connections_global").set_value(self.preferences.get("max_connections_global")) - self.glade.get_widget("spin_max_connections_per_torrent").set_value(self.preferences.get("max_connections_per_torrent")) - self.glade.get_widget("spin_peer_proxy_port").set_value(self.preferences.get("peer_proxy_port")) - self.glade.get_widget("spin_tracker_proxy_port").set_value(self.preferences.get("tracker_proxy_port")) - self.glade.get_widget("spin_dht_proxy_port").set_value(self.preferences.get("dht_proxy_port")) - self.glade.get_widget("spin_web_proxy_port").set_value(self.preferences.get("web_proxy_port")) - self.glade.get_widget("spin_max_half_open").set_value(float(self.preferences.get("max_half_open"))) - self.glade.get_widget("spin_connection_speed").set_value(float(self.preferences.get("connection_speed"))) - self.glade.get_widget("spin_torrents").set_value(float(self.preferences.get("max_active_torrents"))) - self.glade.get_widget("chk_seedbottom").set_active(self.preferences.get("queue_seeds_to_bottom")) - self.glade.get_widget("chk_queue_above_completed").set_sensitive(self.preferences.get("queue_seeds_to_bottom")) - self.glade.get_widget("chk_queue_above_completed").set_active(self.preferences.get("queue_above_completed")) - self.glade.get_widget("chk_autoseed").set_active(self.preferences.get("auto_end_seeding")) - self.glade.get_widget("chk_autotime").set_active(self.preferences.get("auto_time_end_seeding")) - self.glade.get_widget("chk_clear_max_ratio_torrents").set_sensitive(self.preferences.get("auto_end_seeding")) - self.glade.get_widget("chk_clear_max_ratio_torrents").set_active(self.preferences.get("clear_max_ratio_torrents")) - self.glade.get_widget("chk_clear_max_time_torrents").set_sensitive(self.preferences.get("auto_time_end_seeding")) - self.glade.get_widget("chk_clear_max_time_torrents").set_active(self.preferences.get("clear_max_time_torrents")) - self.glade.get_widget("chk_paused").set_active(self.preferences.get("start_paused")) - self.glade.get_widget("ratio_spinner").set_value(self.preferences.get("auto_seed_ratio")) - self.glade.get_widget("time_spinner").set_value(self.preferences.get("auto_seed_time")) - self.glade.get_widget("chk_dht").set_active(self.preferences.get("enable_dht")) - self.glade.get_widget("chk_use_advanced_bar").set_active(self.preferences.get("use_advanced_bar")) - - #smart dialog set sensitivities - if(self.preferences.get("use_default_dir")): - self.glade.get_widget("radio_save_all_to").set_active(True) - else: - self.glade.get_widget("radio_ask_save").set_active(True) - - self.glade.get_widget('chk_min_on_close').set_sensitive( - self.glade.get_widget('chk_use_tray').get_active()) - self.glade.get_widget('chk_enable_multi_only').set_sensitive( - self.glade.get_widget('chk_enable_files_dialog').get_active()) - self.glade.get_widget('chk_start_in_tray').set_sensitive( - self.glade.get_widget('chk_use_tray').get_active()) - self.glade.get_widget('chk_lock_tray').set_sensitive( - self.glade.get_widget('chk_use_tray').get_active()) - self.glade.get_widget('txt_tray_passwd').set_sensitive( - self.glade.get_widget('chk_use_tray').get_active() and \ - self.glade.get_widget('chk_lock_tray').get_active()) - - self.glade.get_widget('spin_port_min').set_sensitive( - not self.glade.get_widget('chk_random_port').get_active()) - self.glade.get_widget('spin_port_max').set_sensitive( - not self.glade.get_widget('chk_random_port').get_active()) - - self.glade.get_widget("ok_button").connect("clicked", - self.ok_clicked, interface) - self.glade.get_widget("cancel_button").connect("clicked", - self.cancel_clicked) - - except KeyError: - pass - # plugin tab - self.store.clear() - for plugin in self.plugins.get_available_plugins(): - #print plugin - if plugin in self.plugins.get_enabled_plugins(): - self.store.append( (plugin, True) ) - else: - self.store.append( (plugin, False) ) - self.glade.get_widget("plugin_text").get_buffer().set_text("") - self.glade.get_widget("plugin_conf").set_sensitive(False) - self.dialog.set_transient_for(window) - self.dialog.show() - - def ok_clicked(self, source, interface): - self.dialog.hide() - import sha - self.preferences.set("encin_state", self.glade.get_widget("combo_encin").get_active()) - self.preferences.set("encout_state", self.glade.get_widget("combo_encout").get_active()) - self.preferences.set("enclevel_type", self.glade.get_widget("combo_enclevel").get_active()) - self.preferences.set("peer_proxy_type", self.glade.get_widget("combo_peer_proxy_type").get_active()) - self.preferences.set("autoload", self.glade.get_widget("chk_autoload").get_active()) - self.preferences.set("send_info", self.glade.get_widget("chk_send_info").get_active()) - self.preferences.set("pref_rc4", self.glade.get_widget("chk_pref_rc4").get_active()) - self.preferences.set("peer_proxy", self.glade.get_widget("chk_peer_proxy").get_active()) - self.preferences.set("tracker_proxy", self.glade.get_widget("chk_tracker_proxy").get_active()) - self.preferences.set("dht_proxy", self.glade.get_widget("chk_dht_proxy").get_active()) - self.preferences.set("web_proxy", self.glade.get_widget("chk_web_proxy").get_active()) - self.preferences.set("use_upnp", self.glade.get_widget("chk_upnp").get_active()) - self.preferences.set("use_lsd", self.glade.get_widget("chk_lsd").get_active()) - self.preferences.set("send_redund", self.glade.get_widget("chk_send_redund").get_active()) - self.preferences.set("tracker_proxy_type", self.glade.get_widget("combo_tracker_proxy_type").get_active()) - self.preferences.set("dht_proxy_type", self.glade.get_widget("combo_dht_proxy_type").get_active()) - self.preferences.set("web_proxy_type", self.glade.get_widget("combo_web_proxy_type").get_active()) - self.preferences.set("new_releases", self.glade.get_widget("chk_new_releases").get_active()) - self.preferences.set("random_port", self.glade.get_widget("chk_random_port").get_active()) - self.preferences.set("use_natpmp", self.glade.get_widget("chk_natpmp").get_active()) - self.preferences.set("use_utpex", self.glade.get_widget("chk_utpex").get_active()) - self.preferences.set("enable_system_tray", self.glade.get_widget("chk_use_tray").get_active()) - self.preferences.set("close_to_tray", self.glade.get_widget("chk_min_on_close").get_active()) - self.preferences.set("start_in_tray", self.glade.get_widget("chk_start_in_tray").get_active()) - self.preferences.set("lock_tray", self.glade.get_widget("chk_lock_tray").get_active()) - if len(self.glade.get_widget("txt_tray_passwd").get_text()) != 40: - password = sha.new(self.glade.get_widget("txt_tray_passwd").get_text()).hexdigest() - else: - password = self.glade.get_widget("txt_tray_passwd").get_text() - self.preferences.set("tray_passwd", password) - self.preferences.set("tracker_proxy_username", self.glade.get_widget("txt_tracker_proxy_username").get_text()) - self.preferences.set("tracker_proxy_password", self.glade.get_widget("txt_tracker_proxy_password").get_text()) - self.preferences.set("tracker_proxy_hostname", self.glade.get_widget("txt_tracker_proxy_hostname").get_text()) - self.preferences.set("web_proxy_username", self.glade.get_widget("txt_web_proxy_username").get_text()) - self.preferences.set("web_proxy_password", self.glade.get_widget("txt_web_proxy_password").get_text()) - self.preferences.set("web_proxy_hostname", self.glade.get_widget("txt_web_proxy_hostname").get_text()) - self.preferences.set("dht_proxy_username", self.glade.get_widget("txt_dht_proxy_username").get_text()) - self.preferences.set("dht_proxy_password", self.glade.get_widget("txt_dht_proxy_password").get_text()) - self.preferences.set("dht_proxy_hostname", self.glade.get_widget("txt_dht_proxy_hostname").get_text()) - self.preferences.set("peer_proxy_username", self.glade.get_widget("txt_peer_proxy_username").get_text()) - self.preferences.set("peer_proxy_password", self.glade.get_widget("txt_peer_proxy_password").get_text()) - self.preferences.set("peer_proxy_hostname", self.glade.get_widget("txt_peer_proxy_hostname").get_text()) - self.preferences.set("use_default_dir", self.glade.get_widget("radio_save_all_to").get_active()) - self.preferences.set("default_autoload_path", self.glade.get_widget("autoload_path_button").get_filename()) - self.preferences.set("default_download_path", self.glade.get_widget("download_path_button").get_filename()) - self.preferences.set("default_torrent_path", self.glade.get_widget("torrent_path_button").get_filename()) - self.preferences.set("enable_files_dialog", self.glade.get_widget("chk_enable_files_dialog").get_active()) - self.preferences.set("enable_multi_only", self.glade.get_widget("chk_enable_multi_only").get_active()) - self.preferences.set("prioritize_first_last_pieces", self.glade.get_widget("chk_prioritize_first_last_pieces").get_active()) - self.preferences.set("auto_seed_ratio", self.glade.get_widget("ratio_spinner").get_value()) - self.preferences.set("auto_end_seeding", self.glade.get_widget("chk_autoseed").get_active()) - self.preferences.set("auto_time_end_seeding", self.glade.get_widget("chk_autotime").get_active()) - self.preferences.set("auto_seed_time", self.glade.get_widget("time_spinner").get_value()) - self.preferences.set("use_compact_storage", self.glade.get_widget("radio_compact_allocation").get_active()) - self.preferences.set("listen_on", [self.glade.get_widget("spin_port_min").get_value(), self.glade.get_widget("spin_port_max").get_value()]) - self.preferences.set("max_upload_speed", self.glade.get_widget("spin_max_upload").get_value()) - self.preferences.set("max_upload_slots_global", int(self.glade.get_widget("spin_max_upload_slots_global").get_value())) - self.preferences.set("max_upload_slots_per_torrent", int(self.glade.get_widget("spin_max_upload_slots_per_torrent").get_value())) - self.preferences.set("max_download_speed", self.glade.get_widget("spin_max_download").get_value()) - self.preferences.set("peer_proxy_port", self.glade.get_widget("spin_peer_proxy_port").get_value()) - self.preferences.set("dht_proxy_port", self.glade.get_widget("spin_dht_proxy_port").get_value()) - self.preferences.set("web_proxy_port", self.glade.get_widget("spin_web_proxy_port").get_value()) - self.preferences.set("tracker_proxy_port", self.glade.get_widget("spin_tracker_proxy_port").get_value()) - self.preferences.set("max_connections_global", int(self.glade.get_widget("spin_max_connections_global").get_value())) - self.preferences.set("max_connections_per_torrent", int(self.glade.get_widget("spin_max_connections_per_torrent").get_value())) - self.preferences.set("max_half_open", int(self.glade.get_widget("spin_max_half_open").get_value())) - self.preferences.set("connection_speed", int(self.glade.get_widget("spin_connection_speed").get_value())) - self.preferences.set("max_active_torrents", int(self.glade.get_widget("spin_torrents").get_value())) - self.preferences.set("queue_seeds_to_bottom", self.glade.get_widget("chk_seedbottom").get_active()) - self.preferences.set("enable_dht", self.glade.get_widget("chk_dht").get_active()) - self.preferences.set("clear_max_ratio_torrents", self.glade.get_widget("chk_clear_max_ratio_torrents").get_active()) - self.preferences.set("clear_max_time_torrents", self.glade.get_widget("chk_clear_max_time_torrents").get_active()) - self.preferences.set("queue_above_completed", self.glade.get_widget("chk_queue_above_completed").get_active()) - self.preferences.set("start_paused", self.glade.get_widget("chk_paused").get_active()) - self.preferences.set("use_advanced_bar", self.glade.get_widget("chk_use_advanced_bar").get_active()) - - interface.apply_prefs() - interface.config.save() - - def cancel_clicked(self, source): - self.dialog.hide() - - def close_clicked(self, source): - self.dialog.hide() - - def old_clicked(self, path): - return self.plugin_clicked(self.view.get_selection(), self.store, path, False) - - def plugin_clicked(self, selection, model, path, is_selected): - if is_selected: - return True - name = model.get_value(model.get_iter(path), 0) - plugin = self.plugins.get_plugin(name) - author = plugin.plugin_author - version = plugin.plugin_version - description = plugin.plugin_description - if name in self.plugins.get_enabled_plugins(): - config = self.plugins.configurable_plugin(name) - self.glade.get_widget("plugin_conf").set_sensitive(config) - else: - self.glade.get_widget("plugin_conf").set_sensitive(False) - self.glade.get_widget("plugin_text").get_buffer( - ).set_text("%s\nBy: %s\nVersion: %s\n\n%s"% - (name, author, version, description)) - return True - - def plugin_toggled(self, renderer, path): - plugin_iter = self.store.get_iter_from_string(path) - plugin_name = self.store.get_value(plugin_iter, 0) - plugin_value = not self.store.get_value(plugin_iter, 1) - self.store.set_value(plugin_iter, 1, plugin_value) - if plugin_value: - self.plugins.enable_plugin(plugin_name) - config = self.plugins.configurable_plugin(plugin_name) - try: - self.glade.get_widget("plugin_conf").set_sensitive(config) - except: - pass - else: - self.plugins.disable_plugin(plugin_name) - self.glade.get_widget("plugin_conf").set_sensitive(False) - - def plugin_pref(self, widget=None): - (model, plugin_iter) = self.view.get_selection().get_selected() - plugin_name = self.store.get_value(plugin_iter, 0) - self.plugins.configure_plugin(plugin_name, self.dialog) - - def TestPort(self, widget): - common.open_url_in_browser('http://www.deluge-torrent.org/test-port.php?port=%s' % self.active_port) - - def toggle_ui(self, widget): - value = widget.get_active() - if widget == self.glade.get_widget('radio_save_all_to'): - self.glade.get_widget('download_path_button').set_sensitive(value) - self.glade.get_widget('autoload_path_button').set_sensitive(value) - self.glade.get_widget('chk_autoload').set_sensitive(value) - elif widget == self.glade.get_widget('chk_autoseed'): - self.glade.get_widget('ratio_spinner').set_sensitive(value) - self.glade.get_widget('chk_clear_max_ratio_torrents').set_sensitive(value) - elif widget == self.glade.get_widget('chk_autotime'): - self.glade.get_widget('time_spinner').set_sensitive(value) - self.glade.get_widget('chk_clear_max_time_torrents').set_sensitive(value) - elif widget == self.glade.get_widget('chk_seedbottom'): - self.glade.get_widget('chk_queue_above_completed').set_sensitive(value) - elif widget == self.glade.get_widget('chk_enable_files_dialog'): - self.glade.get_widget('chk_enable_multi_only').set_sensitive(value) - elif widget == self.glade.get_widget('chk_peer_proxy'): - value = self.glade.get_widget('chk_peer_proxy').get_active() - for x in ['combo_peer_proxy_type', 'txt_peer_proxy_hostname', - 'txt_peer_proxy_username', 'spin_peer_proxy_port', - 'txt_peer_proxy_password']: - self.glade.get_widget(x).set_sensitive(value) - elif widget == self.glade.get_widget('chk_tracker_proxy'): - value = self.glade.get_widget('chk_tracker_proxy').get_active() - for x in ['combo_tracker_proxy_type', 'txt_tracker_proxy_hostname', - 'txt_tracker_proxy_username', 'spin_tracker_proxy_port', - 'txt_tracker_proxy_password']: - self.glade.get_widget(x).set_sensitive(value) - elif widget == self.glade.get_widget('chk_dht_proxy'): - value = self.glade.get_widget('chk_dht_proxy').get_active() - for x in ['combo_dht_proxy_type', 'txt_dht_proxy_hostname', - 'txt_dht_proxy_username', 'spin_dht_proxy_port', - 'txt_dht_proxy_password']: - self.glade.get_widget(x).set_sensitive(value) - elif widget == self.glade.get_widget('chk_web_proxy'): - value = self.glade.get_widget('chk_web_proxy').get_active() - for x in ['combo_web_proxy_type', 'txt_web_proxy_hostname', - 'txt_web_proxy_username', 'spin_web_proxy_port', - 'txt_web_proxy_password']: - self.glade.get_widget(x).set_sensitive(value) - elif widget == self.glade.get_widget('chk_use_tray'): - self.glade.get_widget('chk_min_on_close').set_sensitive(value) - self.glade.get_widget('chk_start_in_tray').set_sensitive(value) - self.glade.get_widget('chk_lock_tray').set_sensitive(value) - self.glade.get_widget('txt_tray_passwd').set_sensitive(value and \ - self.glade.get_widget('chk_lock_tray').get_active()) - elif widget == self.glade.get_widget('chk_lock_tray'): - self.glade.get_widget('txt_tray_passwd').set_sensitive(value) - elif widget == self.glade.get_widget('chk_random_port'): - self.glade.get_widget('spin_port_min').set_sensitive(False) - self.glade.get_widget('spin_port_max').set_sensitive(False) - if not value: - self.glade.get_widget('spin_port_min').set_sensitive(True) - self.glade.get_widget('spin_port_max').set_sensitive(True) - -class MergeDlg: - def __init__(self): - self.glade = gtk.glade.XML(common.get_glade_file("merge_dialog.glade"), - domain='deluge') - self.dialog = self.glade.get_widget("merge_dialog") - self.dialog.set_position(gtk.WIN_POS_CENTER) - if not common.windows_check(): - self.dialog.set_icon(common.get_logo(18)) - - def show(self, window): - self.dialog.set_transient_for(window) - self.dialog.show() - r = self.dialog.run() - self.dialog.hide() - - return r - -class FilesDlg: - def __init__(self, dumped_torrent): - self.glade = gtk.glade.XML(common.get_glade_file("files_dialog.glade"), - domain='deluge') - self.dialog = self.glade.get_widget("file_dialog") - self.dialog.set_position(gtk.WIN_POS_CENTER) - if not common.windows_check(): - self.dialog.set_icon(common.get_logo(18)) - - self.files_manager = files.FilesDialogManager( - self.glade.get_widget("file_view"), - dumped_torrent) - self.files_manager.build_file_view() - self.files_manager.prepare_file_store() - - def show(self, window): - #clear private setting - self.glade.get_widget("chk_setpriv").set_active(False) - self.dialog.set_transient_for(window) - self.dialog.show() - r = self.dialog.run() - self.dialog.hide() - - return r - - def is_private_flag_checked(self): - return self.glade.get_widget("chk_setpriv").get_active() - - def get_priorities(self): - return self.files_manager.get_priorities() - -def show_about_dialog(window): - def url_hook(dialog, url): - common.open_url_in_browser(url) - - gtk.about_dialog_set_url_hook(url_hook) - abt = gtk.glade.XML(common.get_glade_file("aboutdialog.glade")).get_widget("aboutdialog") - abt.set_transient_for(window) - abt.set_name(common.PROGRAM_NAME) - abt.set_version(common.PROGRAM_VERSION) - abt.set_comments("Deluge is a full-featured BitTorrent\nclient for Linux, Mac OS X and Windows") - abt.set_documenters(["Marcos Pinto"]) - abt.set_authors(["Zach Tibbitts", "Alon Zakai", "Marcos Pinto", "Andrew Resch", "Alex Dedul"]) - abt.set_artists(["Andrew Wedderburn"]) - abt.set_translator_credits("Ahmad Farghal\nA.Matveev\nAaron Wang Shi\nabbigss\nAbcx\nAccord Tsai\nActam\nAdam\nAdrian Goll\nAhmades\nakira\nAlan Pepelko\nAlberto\nAlberto Ferrer\nalcatr4z\nAleksej Korgenkov\nAlessio Treglia\nAlexander Matveev\nAlexander Taubenkorb\nAlexander Yurtsev\nAlexandre Martani\nAlexandre Rosenfeld\nAlexandre Sapata Carbonell\nAlin Claudiu Radut\nAlSim\nAlvaro Carrillanca P.\nAndrea Ratto\nAndrea Tarocchi\nAndreas Johansson\nAndreas Str\nAndreiF\nandrewh\nAndris Karasz\nAngel Guzman Maeso\nAníbal Deboni Neto\nanimarval\nAnton Yakutovich\nAntonio Cono\nantoniojreyes\nantou\nArkadiusz Kalinowski\nArtin\nartir\nAthanasios Lefteris\nAugusta Carla Klug\naxaard\nAxelRafn\nAyont\nb3rx\nBae Taegil\nBajusz Tamás\nBalaam's Miracle\nBent Ole Fosse\nbeyonet\nbigx\nBjorn Inge Berg\nblackbird\nBlackeyed\nblackmx\nBlutheo\nbob00work\nboenki\nBoone\nBranislav Jovanović\nbronze\nbrownie\nBrus46\nbumper\nbutely\nc0nfidencal\ncassianoleal\nCésar Rubén\nChangHyo Jeong\nchicha\nChien Cheng Wei\nChristian Kopac\nchristooss\nCityAceE\nckaya\nClopy\nClusty\ncnu\nCommandant\nCoolmax\ncosmix\nCostin Chirvasuta\nCoVaLiDiTy\nCrispin Kirchner\nCruster\nCybolic\nDan Bishop\nDanek\nDani\nDaniel Frank\nDaniel Høyer Iversen\nDaniel Marynicz\nDaniel Nylander\nDaniel Patriche\nDaniel Schildt\ndarh00\nDaria Michalska\nDarkenCZ\nDaspah\nDavid Eurenius\nDavid Machakhelidze\ndavidhjelm\nDawid Dziurdzia\ndcruz\nDeady\ndi0rz`\nDialecti Valsamou\nDiego Medeiros\nDkzoffy\ndmig\nDmitry Olyenyov\nDominik Kozaczko\nDominik Lübben\ndoomster\nDorota Król\nDoyen Philippe\nDread Knight\nDreamSonic\nduan\nDuong Thanh An\nDvoglavaZver\ndwori\ndylansmrjones\nEbuntor\nEdgar Alejandro Jarquin Flores\nEetu\nekerazha\neliasj\nelparia\nEmberke\nEmiliano Goday Caneda\nEndelWar\nercangun\nÉric Lassauge\nErlend Finvåg\nEvgeni Spasov\nFabian Ordelmans\nFabio Mazanatti\nFábio Nogueira\nFaCuZ\nFelipe Lerena\nFernando Pereira\nfjetland\nFlorian Schäfer\nFolke\nForce\nfosk\nfragarray\nfreddeg\nFrédéric Perrin\nFredrik Kilegran\nFreeAtMind\nFulvio Ciucci\nGabor Kelemen\nGaussian\ngdevitis\nGeorg Brzyk\nGeorg Sieber\nGeorgi Arabadjiev\nGerd Radecke\ngergo86\nGermán Heusdens\nGianni Vialetto\nGigih Aji Ibrahim\nGiorgio Wicklein\nGiovanni Rapagnani\ngl\nglen\ngranjerox\nGreen Fish\nGreyhound\nguillaume\nGuillaume Pelletier\nGustavo Henrique Klug\ngutocarvalho\nHans Rødtang\nHargas Gábor\nhasardeur\nHeitor Thury Barreiros Barbosa\nhelios91940\nhelix84\nHelton Rodrigues\nHendrik Luup\nHenrique Ferreiro\nHenry Goury-Laffont\nHezy Amiel\nHipi\nhokten\nHolmsss\nhristo.num\nIarwain\nibe\nibear\nId2ndR\nIgor Zubarev\nimen\nInuktitut\nIoannis Koniaris\nIstvan Nyitrai\nIvan Petrovic\nIvan Prignano\nJack Shen\njackmc\nJacques Stadler\nJakub Korbel\nJames Nealon\nJan Kaláb\nJan Niklas Hasse\nJanek Thomaschewski\nJasper Groenewegen\nJavi Rodríguez\njeannich\nJeff Bailes\nJesse Zilstorff\nJoan Duran\nJoão Santos\nJochen Schäfer\nJoe Anderson\nJohn Garland\nJojan\njollyr0ger\nJonas Bo Grimsgaard\nJonas Granqvist\nJonas Slivka\nJonathan Zeppettini\nJørgen\nJørgen Tellnes\njosé\nJosé Geraldo Gouvêa\nJosé Lou C.\nJose Sun\nJr.\nJukka Kauppinen\njulietgolf\nJusic\nJustzupi\nKaarel\nKai Thomsen\nKamil Páral\nKane_F\nKateikyoushii\nkaxhinaz\nKazuhiro NISHIYAMA\nKerberos\nKeresztes Ákos\nkevintyk\nkiersie\nKim Lübbe\nKimbo^\nkitzOgen\nkluon\nkmikz\nkoleoptero\nKőrösi Krisztián\nKostas\nKouta\nKrakatos\nKrešo Kunjas\nkripkenstein\nKristian Øllegaard\nKristoffer Egil Bonarjee\nKrzysztof Janowski\nl3estkunG\nlaughterwym\nLaur Mõtus\nlazka\nlebinh\nLKRaider\nLow Kian Seong\nLuca Ferretti\nLuis Gomes\nLuis Reis\nM.Kitchen\nMaciej Chojnacki\nMads Peter Rommedahl\nMajor Kong\nmalde\nMara Sorella\nmarazmista\nMarcin\nMarcin Falkiewicz\nMarco da Silva\nMarco de Moulin\nMarco Rodrigues\nmarcobra\nMarcos Escalier\nMarcos Pinto\nMarcus Ekstrom\nMario César Señoranis\nMario Munda\nMarius Andersen\nMarius Hudea\nMarius Mihai\nMariusz Cielecki\nMark Krapivner\nmarko-markovic\nMarkus Sutter\nMartin\nMartin Dybdal\nMartin Iglesias\nMartin Lettner\nMartin Pihl\nMasoud Kalali\nmat02\nMatej Urbančič\nMathias-K\nMatrik\nMatteo Renzulli\nMatthias Benkard\nMatthias Mailänder\nMert Dirik\nmhietar\nMichael Budde\nMichal Kaliszka\nMichał Tokarczyk\nMiguel Pires da Rosa\nMihai Capotă\nMikael Fernblad\nMike Sierra\nMike Sierra\nMilan Prvulović\nMilo Casagrande\nMiroslav Matejaš\nmithras\nMitja Pagon\nMohamed Magdy\nmoonkey\nMrBlonde\nmrtbzkrt\nmuczy\nMustafa Temizel\nmvoncken\nNagyMarton\nNeil Lin\nNicklas Larsson\nNicola Piovesan\nNicolaj Wyke\nNicolas Velin\nnik\nNiko_Thien\nNikolai M. Riabov\nnoisemonkey\nnosense\nNuno Estêvão\nNuno Santos\nnxxs\nnyo\noldbeggar\nOlivier FAURAX\nosantana\nOsman Tosun\nOssiR\notypoks\nounn\nOz123\nÖzgür BASKIN\nPablo Ledesma\nPål-Eivind Johnsen\npano\nPaolo Naldini\nPattogoTehen\nPaul Lange\nPavcio\nPaweł Wysocki\nPedro Brites Moita\nPedro Clemente Pereira Neto\nPekka Niemistö\nPenzo\nperdido\nPeter Kotrcka\nPeter Van den Bosch\nPetter Eklund\nPetter Viklund\nphatsphere\nPhilipi\nPhilippides Homer\npidi\nPierre Quillery\nPierre Slamich\nPiotr Strębski\nPittmann Tamás\nPrescott\nPumy\npushpika \nPY\nqubicllj\nr21vo\nrainofchaos\nRajbir\nras0ir\nRat\nremus\nRenato\nRene Pärts\nRicardo Duarte\nRichard\nRobert Hrovat\nRobert Lundmark\nRoberth Sjonøy\nRobin Jakobsson\nRodrigo Donado\nRoel Groeneveld\nrohmaru\nRolf Christensen\nRoni Kantis\nRonmi\nRostislav Raykov\nroyto\nRui Moura\nRuiAmaro\nRusna\nRytis\nSam Azab\nSami Koskinen\nSamir van de Sand\nSamuel R. C. Vale\nsanafrato\nSanti\nSanti Martínez Cantelli\nSargate Kanogan\nSarmad Jari\nSaša Bodiroža\nsat0shi\nSavvas Radević\nSebastian Krauß\nSebastián Porta\nSedir\nsekolands\nsemsomi\nSergii Golovatiuk\nSergio\nsetarcos\nSheki\nSheki\nshifty\nShironeko\nShlomil\nSimone Tolotti\nSimone Vendemia\nsimonkoco\nskoruppa\nSławomir Więch\nslyon\nsmoke\nSonja\nspin_555\nSpiziuz\nSpyros Theodoritsis\nSqUe\nsrtck\nStefan Horning\nStefano Maggiolo\nStefano Roberto Soleti\nsteinberger\nStephan Klein\nStéphane Travostino\nStian24\nstylius\nSunjae Park\nSusana Pereira\nszymon siglowy\nthamood\nThanos Chatziathanassiou\nThe Jedi\nThéophane Anestis\nTiago Silva\nTiago Sousa\nTikkel\nTim Bordemann\nTim Fuchs\nTim Kornhammar\ntim__b\nTimo\nTimo Jyrinki\nTimothy Babych\nTitkosRejtozo\nTom\nTom Mannerhagen\nTom Verdaat\nTomas Gustavsson\nTomas Valentukevičius\nTomislav Plavčić\nTommy Mikkelsen\nToudi\ntqm_z\nTrapanator\nTribaal\nTuomo Sipola\nturbojugend_gr\nTurtle.net\ntwilight\ntymmej\numarzuki\nunikob\nVadim Gusev\nVagi\nValmantas Palikša\nVASKITTU\nvetal17\nvicedo\nviki\nvillads hamann\nvinchi007\nVinícius de Figueiredo Silva\nvinz\nvirtoo\nVitor Caike\nVitor Lamas Gatti\nWanderlust\nwarddr\nWebCrusader\nwebdr\nWentao Tang\nWorld Sucks\nXabi Ezpeleta\nXavi de Moner\nXavierToo\nXChesser\nXiaodong Xu\nxyb\nYasen Pramatarov\nZanDaTHraX\nzekopeko\nzhuqin\nZissan\nАртём Попов") - abt.set_license(_("Deluge is free software, you can redistribute it and/or\nmodify it under the terms of the GNU General Public\n License as published by the Free Software Foundation,\neither version 2 of the License, or (at your option) any\nlater version. Deluge is distributed in the hope that it\nwill be useful, but WITHOUT ANY WARRANTY, without even \nthe implied warranty of MERCHANTABILITY or FITNESS\nFOR A PARTICULAR PURPOSE. See the GNU General\nPublic License for more details. You should have received\na copy of the GNU General Public License along with\nDeluge, but if not, write to the Free Software Foundation,\n Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-\n1301 USA")) - abt.set_website("http://deluge-torrent.org") - abt.set_website_label("http://deluge-torrent.org") - if not common.windows_check(): - abt.set_icon(common.get_logo(18)) - abt.set_logo(gtk.gdk.pixbuf_new_from_file( - common.get_pixmap("deluge-about.png"))) - abt.show_all() - abt.run() - abt.hide_all() - -def show_popup_warning(window, message): - warner = gtk.MessageDialog(parent = window, - flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - buttons= gtk.BUTTONS_OK, - message_format=message, - type = gtk.MESSAGE_WARNING) - warner.run() - warner.destroy() - -def show_popup_question(window, message): - asker = gtk.MessageDialog(parent = window, - flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - buttons = gtk.BUTTONS_YES_NO, - message_format=message, - type=gtk.MESSAGE_QUESTION) - result = asker.run() - asker.destroy() - if result == gtk.RESPONSE_YES: - return True - elif result == gtk.RESPONSE_NO: - return False - elif result == gtk.RESPONSE_DELETE_EVENT: - return False - else: - return False - - -## Browse for .torrent files -def show_file_open_dialog(parent, title=None): - if title is None: - title = _("Choose a .torrent file") - chooser = gtk.FileChooserDialog(title, parent, gtk.FILE_CHOOSER_ACTION_OPEN, - buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) - - f0 = gtk.FileFilter() - f0.set_name(_("Torrent files")) - f0.add_pattern("*." + "torrent") - chooser.add_filter(f0) - f1 = gtk.FileFilter() - f1.set_name(_("All files")) - f1.add_pattern("*") - config = pref.Preferences() - chooser.set_current_folder(config.get("open_torrent_dialog_path")) - chooser.add_filter(f1) - chooser.set_select_multiple(True) - if not common.windows_check(): - chooser.set_icon(common.get_logo(18)) - chooser.set_property("skip-taskbar-hint", True) - - response = chooser.run() - if response == gtk.RESPONSE_OK: - result = chooser.get_filenames() - config.set("open_torrent_dialog_path", chooser.get_current_folder()) - else: - result = None - chooser.destroy() - return result - -def show_directory_chooser_dialog(parent, title): - chooser = gtk.FileChooserDialog(title, parent, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, - buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) - if not common.windows_check(): - chooser.set_icon(common.get_logo(18)) - chooser.set_property("skip-taskbar-hint", True) - config = pref.Preferences() - current_folder = config.get("choose_directory_dialog_path") - if current_folder != None: - chooser.set_current_folder(current_folder) - if chooser.run() == gtk.RESPONSE_OK: - result = chooser.get_filename() - config.set("choose_directory_dialog_path", result) - else: - result = None - chooser.destroy() - return result diff --git a/src/files.py b/src/files.py deleted file mode 100644 index 49c1087cb..000000000 --- a/src/files.py +++ /dev/null @@ -1,174 +0,0 @@ -# -*- coding: utf-8 -*- -# -# files.py -# -# Copyright (C) Zach Tibbitts 2006 -# -# 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 2, 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 itertools import izip - -import gobject -import gtk - -import common -import core -import dgtk -import pref - -class FilesBaseManager(object): - def __init__(self, file_view, file_store): - self.config = pref.Preferences() - - self.file_view = file_view - - self.glade = gtk.glade.XML(common.get_glade_file("file_tab_menu.glade"), - domain='deluge') - self.file_menu = self.glade.get_widget("file_tab_menu") - self.glade.signal_autoconnect({ - "open_file" : self.open_file, - "select_all": self.file_select_all, - "unselect_all": self.file_unselect_all, - "priority_dont_download": self.priority_clicked, - "priority_normal": self.priority_clicked, - "priority_high": self.priority_clicked, - "priority_highest": self.priority_clicked, - }) - - self.file_store = file_store - # We need file_store_sorted so original file_store keeps unchanged - # when file_view is sorted. And from file_store we have to pass - # files priorities to manager.prioritize_files() in the exact same - # order as we get files from manager.get_torrent_file_info() - self.file_store_sorted = gtk.TreeModelSort(self.file_store) - - def open_file(self): - pass - - def build_file_view(self): - def priority(column, cell, model, iter, data): - priority = common.fpriority(model.get_value(iter, data)) - cell.set_property("text", priority) - - filename_column = dgtk.add_text_column(self.file_view, _("Filename"), \ - 0, width=self.config.get("filename_f_width")) - filename_column.set_expand(True) - size_column = dgtk.add_func_column(self.file_view, _("Size"), dgtk.cell_data_size, - 1, width=self.config.get("size_f_width")) - priority_column = dgtk.add_func_column(self.file_view, _("Priority"), \ - priority, 2, width=self.config.get("priority_f_width")) - self.file_view.set_model(self.file_store_sorted) - self.file_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE) - - self.file_view.connect("button-press-event", self.mouse_clicked) - - def clear_file_store(self): - self.file_store.clear() - self.file_store_dict = {} - - def prepare_file_store(self): - pass - - def file_select_all(self, widget): - self.file_view.get_selection().select_all() - - def file_unselect_all(self, widget): - self.file_view.get_selection().unselect_all() - - def compact_allocation_warning(self): - msgBox = gtk.MessageDialog(parent = None, buttons = gtk.BUTTONS_OK, - message_format = (_("File priority can only be set when using full allocation.\nPlease change your preference to disable compact allocation, then remove and re-add this torrent."))) - msgBox.run() - msgBox.destroy() - - def priority_clicked(self, widget): - widget_name = widget.get_name() - priority = {'priority_dont_download': core.PRIORITY_DONT_DOWNLOAD, - 'priority_normal': core.PRIORITY_NORMAL, - 'priority_high': core.PRIORITY_HIGH, - 'priority_highest': core.PRIORITY_HIGHEST}[widget_name] - - selected_paths = self.file_view.get_selection().get_selected_rows()[1] - for path in selected_paths: - child_path = self.file_store_sorted.\ - convert_path_to_child_path(path) - - self.file_store.set_value(self.file_store.get_iter(child_path), 2, - priority) - self.update_priorities() - - def mouse_clicked(self, widget, event): - if event.button == 3: - data = self.file_view.get_path_at_pos(int(event.x), int(event.y)) - if data is None: - return True - - path = data[0] - is_selected = self.file_view.get_selection().path_is_selected(path) - if not is_selected: - self.file_view.grab_focus() - self.file_view.set_cursor(path) - self.file_menu.popup(None, None, None, event.button, event.time) - - return is_selected - else: - return False - - def update_priorities(self): - pass - -class FilesDialogManager(FilesBaseManager): - def __init__(self, file_view, dumped_torrent): - file_store = gtk.ListStore(str, gobject.TYPE_UINT64, - gobject.TYPE_UINT) - super(FilesDialogManager, self).__init__(file_view, file_store) - - self.dumped_torrent = dumped_torrent - self.config = pref.Preferences() - - # Hide Open File menu item as it's not applicable when torrent is - # not added yet - self.glade.get_widget("open_file").hide() - self.glade.get_widget("open_file_separator").hide() - - def prepare_file_store(self): - for file in self.dumped_torrent: - self.file_store.append([file['path'], file['size'], - core.PRIORITY_NORMAL]) - - def priority_clicked(self, widget): - if self.config.get("use_compact_storage"): - self.compact_allocation_warning() - else: - super(FilesDialogManager, self).priority_clicked(widget) - - def get_priorities(self): - file_priorities = [] - for x in self.file_store: - file_priorities.append(x[2]) - - return file_priorities diff --git a/src/interface.py b/src/interface.py deleted file mode 100644 index a928b5339..000000000 --- a/src/interface.py +++ /dev/null @@ -1,1760 +0,0 @@ -# -*- coding: utf-8 -*- -# -# interface.py -# -# Copyright (C) Zach Tibbitts 2006 -# -# 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 2, 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. - -import os -import signal -import gobject -import pygtk -pygtk.require('2.0') -import gtk - -import common -import core -import dialogs -import dgtk -import ipc_manager -import plugins -import tab_details - -class DelugeGTK: - def __init__(self, config_dir=None): - if config_dir: - common.CONFIG_DIR = config_dir - base_change = True - self.ipc_manager = ipc_manager.Manager(self) - #Start the Deluge Manager: - self.manager = core.Manager(common.CLIENT_CODE, common.CLIENT_VERSION, - '%s %s' % (common.PROGRAM_NAME, common.PROGRAM_VERSION), - common.CONFIG_DIR, base_change=base_change) - - self.plugins = plugins.PluginManager(self.manager, self) - self.plugins.add_plugin_dir(common.PLUGIN_DIR) - if os.path.isdir(os.path.join(common.CONFIG_DIR , 'plugins')): - self.plugins.add_plugin_dir(os.path.join(common.CONFIG_DIR, - 'plugins')) - self.plugins.scan_for_plugins() - self.config = self.manager.get_config() - #Set up the interface: - self.wtree = gtk.glade.XML(common.get_glade_file("delugegtk.glade"), - domain='deluge') - self.window = self.wtree.get_widget("main_window") - self.toolbar = self.wtree.get_widget("tb_left") - self.window.drag_dest_set(gtk.DEST_DEFAULT_ALL, [('text/uri-list', 0, - 80)], gtk.gdk.ACTION_COPY) - self.window.connect("delete_event", self.close) - self.window.connect("key_press_event", self.key_pressed) - self.window.connect("drag_data_received", self.on_drag_data) - self.window.connect("window-state-event", self.window_state_event) - self.window.connect("configure-event", self.window_configure_event) - self.window.set_title(common.PROGRAM_NAME) - if not common.windows_check(): - self.window.set_icon(common.get_logo(48)) - # self.notebook is used by plugins - self.notebook = self.wtree.get_widget("torrent_info") - self.notebook.connect("switch-page", self.notebook_switch_page) - self.notebook.connect("page-reordered", self.notebook_page_reordered) - self.notebook.connect("page-added", self.notebook_page_added) - - - # Tabs - self.tab_details = tab_details.DetailsTabManager(self.wtree, - self.manager) - - self.statusbar = self.wtree.get_widget("statusbar") - - self.build_tray_icon() - self.has_tray = True - - self.build_torrent_table() - self.load_status_icons() - - # Set the Torrent menu bar sub-menu to the same as the right-click - #Torrent pop-up menu - self.wtree.get_widget("menu_torrent").set_submenu(self.torrent_menu) - self.wtree.get_widget("menu_torrent").set_sensitive(False) - - self.connect_signals() - - try: - self.load_window_settings() - except KeyError: - pass - - self.apply_prefs() - self.load_window_geometry() - # Boolean used in update method to help check whether gui - # should be updated and is set by the window_state_event method - self.is_minimized = False - - # Boolean set to true if window is not minimized and is "visible" - self.update_interface = True - - def send_info(): - import time - - def _run_script(): - common.send_info(self.config.get("enabled_plugins")) - - info_file = os.path.join(common.CONFIG_DIR, 'infosent') - - # Check if we've done this within the last week - if os.path.exists(info_file): - if time.time() - os.stat(info_file)[8] >= 60 * 60 * 24 * 7: - _run_script() - else: - _run_script() - - if self.config.get("send_info"): - send_info() - - try: - import gnome.ui - self.client = gnome.ui.Client() - self.client.connect("die", self.shutdown) - except: - pass - - signal.signal(signal.SIGINT, self.shutdown) - signal.signal(signal.SIGTERM, self.shutdown) - if not common.windows_check(): - signal.signal(signal.SIGHUP, self.shutdown) - else: - from win32api import SetConsoleCtrlHandler - from win32con import CTRL_CLOSE_EVENT - result = 0 - def win_handler(self, ctrl_type): - if ctrl_type == CTRL_CLOSE_EVENT: - self.shutdown() - result = 1 - return result - SetConsoleCtrlHandler(win_handler) - - self.dht_timer = 0 - self.dht_skip = False - for torrent in self.manager.get_queue(): - unique_ID = self.manager.get_torrent_unique_id(torrent) - try: - if self.manager.unique_IDs[unique_ID].trackers_changed: - self.manager.replace_trackers(unique_ID, \ - self.manager.unique_IDs[unique_ID].trackers) - except AttributeError: - pass - - def connect_signals(self): - self.wtree.signal_autoconnect({ - ## File Menu - "add_torrent": self.add_torrent_clicked, - "add_torrent_url": self.add_torrent_url_clicked, - "remove_torrent": self.remove_torrent_clicked, - "menu_quit": self.quit, - ## Edit Menu - "select_all_torrents": self.select_all_torrents, - "plugin_clicked": self.show_plugin_dialog_clicked, - "pref_clicked": self.show_preferences_dialog_clicked, - ## View Menu - "toolbar_toggle": self.toolbar_toggle, - "infopane_toggle": self.infopane_toggle, - "size_toggle": self.size_toggle, - "status_toggle": self.status_toggle, - "seeders_toggle": self.seeders_toggle, - "peers_toggle": self.peers_toggle, - "dl_toggle": self.dl_toggle, - "ul_toggle": self.ul_toggle, - "eta_toggle": self.eta_toggle, - "availability_toggle": self.availability_toggle, - "share_toggle": self.share_toggle, - ## Help Menu - "launch_homepage": self.launch_homepage, - "launch_community": self.launch_community, - "launch_faq": self.launch_faq, - "launch_donate": self.launch_donate, - "show_about_dialog": self.show_about_dialog, - "launchpad": self.launchpad, - "run_wizard": self.run_wizard, - ## Toolbar - "tor_start": self.tor_start, - "tor_pause": self.tor_pause, - "update_tracker": self.update_tracker, - "scrape_tracker": self.scrape_tracker, - "clear_finished": self.clear_finished, - "queue_up": self.q_torrent_up, - "queue_down": self.q_torrent_down - }) - - def notebook_switch_page(self, notebook, page, page_num): - # Force an update when user changes the notebook tab. - # See notes in torrent_clicked() why we doing it this way. The only - # difference here is that notebook_switch_page() is called by signal - # 'switch-page' from GTK before notebook is switched to page_num, so - # queue up update routines so they are called after page is actually - # showed. See docs on 'switch-page' signal for gtk.Notebook. - - gobject.timeout_add(10, self.update_torrent_info_widget) - gobject.timeout_add(10, self.plugins.update_active_plugins) - - def notebook_page_reordered(self, notebook, page, page_num): - if page_num == 0: - notebook.reorder_child(page, 1) - - def notebook_page_added(self, notebook, page, page_num): - notebook.set_tab_reorderable(page, True) - - def pause_all_clicked(self, arg=None): - self.manager.pause_all() - - def launch_browser_clicked(self, arg=None): - try: - import browser - browser.Browser() - except: - dialogs.show_popup_warning(self.window, _("Unable to state browser. \ -Make sure you have python-gnome2-extras installed or try setting your LD_LIBRARY_PATH \ -and MOZILLA_FIVE_HOME environment variables to /usr/lib/firefox")) - - def resume_all_clicked(self, arg=None): - self.manager.resume_all() - - def key_pressed(self, widget, key): - """captures keys""" - if key.keyval == gtk.keysyms.Delete: - self.remove_torrent_clicked() - elif key.keyval in (gtk.keysyms.N, gtk.keysyms.n) and (key.state & \ - gtk.gdk.CONTROL_MASK) != 0: - self.add_torrent_clicked() - elif key.keyval in (gtk.keysyms.L, gtk.keysyms.l) and (key.state & \ - gtk.gdk.CONTROL_MASK) != 0: - self.add_torrent_url_clicked() - elif key.keyval in (gtk.keysyms.P, gtk.keysyms.p) and (key.state & \ - gtk.gdk.CONTROL_MASK) != 0: - self.tor_pause(widget) - elif key.keyval in (gtk.keysyms.R, gtk.keysyms.r) and (key.state & \ - gtk.gdk.CONTROL_MASK) != 0: - self.tor_start(widget) - - def build_tray_icon(self): - self.tray_icon = gtk.status_icon_new_from_icon_name('deluge') - - self.tray_glade = gtk.glade.XML(common.get_glade_file\ - ("tray_menu.glade"), domain='deluge') - self.tray_menu = self.tray_glade.get_widget("tray_menu") - self.tray_glade.signal_autoconnect({ - "quit": self.quit, - "pause_all": self.pause_all_clicked, - "resume_all": self.resume_all_clicked, - "add_torrent": self.add_torrent_clicked, - "add_torrent_url": self.add_torrent_url_clicked, - "show_hide_window_toggled": self.show_hide_window_toggled - }) - - self.tray_glade.get_widget("download-limit-image").set_from_file( - common.get_pixmap('downloading16.png')) - self.tray_glade.get_widget("upload-limit-image").set_from_file( - common.get_pixmap('seeding16.png')) - self.build_tray_bwsetsubmenu() - - self.tray_icon.connect("activate", self.tray_clicked) - self.tray_icon.connect("popup-menu", self.tray_popup) - - def tray_popup(self, status_icon, button, activate_time): - if self.window.get_property("visible"): - self.tray_glade.get_widget("show_hide_window").set_active(True) - else: - self.tray_glade.get_widget("show_hide_window").set_active(False) - - self.tray_menu.popup(None, None, gtk.status_icon_position_menu, - button, activate_time, status_icon) - - def build_tray_bwsetsubmenu(self): - # Create the Download speed list sub-menu - self.submenu_bwdownset = self.build_menu_radio_list( - self.config.get("tray_downloadspeedlist"), self.tray_setbwdown, - self.config.get("max_download_speed"), _("KiB/s"), - show_notset=True, show_other=True) - - # Create the Upload speed list sub-menu - self.submenu_bwupset = self.build_menu_radio_list( - self.config.get("tray_uploadspeedlist"), self.tray_setbwup, - self.config.get("max_upload_speed"), _("KiB/s"), - show_notset=True, show_other=True) - - # Add the sub-menus to the tray menu - self.tray_glade.get_widget("download_limit").set_submenu( - self.submenu_bwdownset) - self.tray_glade.get_widget("upload_limit").set_submenu( - self.submenu_bwupset) - - # Show the sub-menus for all to see - self.submenu_bwdownset.show_all() - self.submenu_bwupset.show_all() - - def build_menu_radio_list(self, value_list, callback, pref_value=None, - suffix=None, show_notset=False, notset_label=None, notset_lessthan=0, - show_other=False, show_activated=False, activated_label=None): - # Build a menu with radio menu items from a list and connect them to - # the callback. The pref_value is what you would like to test for the - # default active radio item. - # Setting show_unlimited will include an Unlimited radio item - if notset_label is None: - notset_label = _("Unlimited") - - if activated_label is None: - activated_label = _("Activated") - - menu = gtk.Menu() - group = None - if show_activated is False: - for value in sorted(value_list): - if suffix != None: - menuitem = gtk.RadioMenuItem(group, str(value) + " " + \ - suffix) - else: - menuitem = gtk.RadioMenuItem(group, str(value)) - - group = menuitem - - if value == pref_value and pref_value != None: - menuitem.set_active(True) - - if callback != None: - menuitem.connect("toggled", callback) - - menu.append(menuitem) - - if show_activated is True: - for value in sorted(value_list): - menuitem = gtk.RadioMenuItem(group, str(activated_label)) - - group = menuitem - - if value == pref_value and pref_value != None: - menuitem.set_active(True) - - if callback != None: - menuitem.connect("toggled", callback) - - menu.append(menuitem) - - if show_notset: - menuitem = gtk.RadioMenuItem(group, notset_label) - if pref_value < notset_lessthan and pref_value != None: - menuitem.set_active(True) - if show_activated and pref_value == 1: - menuitem.set_active(True) - menuitem.connect("toggled", callback) - menu.append(menuitem) - - # Add the Other... menuitem - if show_other is True: - menuitem = gtk.SeparatorMenuItem() - menu.append(menuitem) - menuitem = gtk.MenuItem(_("Other...")) - menuitem.connect("activate", callback) - menu.append(menuitem) - - return menu - - def tray_setbwdown(self, widget, data=None): - str_bwdown = widget.get_children()[0].get_text().rstrip(" " + - _("KiB/s")) - if str_bwdown == _("Unlimited"): - str_bwdown = -1 - - if str_bwdown == _("Other..."): - dialog_glade = gtk.glade.XML(common.get_glade_file( - "dgtkpopups.glade")) - speed_dialog = dialog_glade.get_widget("speed_dialog") - spin_title = dialog_glade.get_widget("spin_title") - spin_title.set_text(_("Download Speed (KiB/s):")) - spin_speed = dialog_glade.get_widget("spin_speed") - speed_dialog.set_transient_for(self.window) - speed_dialog.set_modal(True) - spin_speed.set_value(self.config.get("max_download_speed")) - spin_speed.select_region(0, -1) - response = speed_dialog.run() - if response == 1: # OK Response - str_bwdown = spin_speed.get_value() - else: - speed_dialog.destroy() - return - speed_dialog.destroy() - - self.config.set("max_download_speed", float(str_bwdown)) - self.apply_prefs() - - def tray_setbwup(self, widget, data=None): - str_bwup = widget.get_children()[0].get_text().rstrip(" " + - _("KiB/s")) - if str_bwup == _("Unlimited"): - str_bwup = -1 - - if str_bwup == _("Other..."): - dialog_glade = gtk.glade.XML(common.get_glade_file( - "dgtkpopups.glade")) - speed_dialog = dialog_glade.get_widget("speed_dialog") - spin_title = dialog_glade.get_widget("spin_title") - spin_title.set_text(_("Upload Speed (KiB/s):")) - spin_speed = dialog_glade.get_widget("spin_speed") - spin_speed.set_value(self.config.get("max_upload_speed")) - spin_speed.select_region(0, -1) - response = speed_dialog.run() - if response == 1: # OK Response - str_bwup = spin_speed.get_value() - else: - speed_dialog.destroy() - return - speed_dialog.destroy() - - self.config.set("max_upload_speed", float(str_bwup)) - self.apply_prefs() - - # Use is_showing_dlg argument as a kind of static variable to not add - # unlock tray dialog state to instance where it will be not used except as - # in this method. Assigning list to is_showing_dlg is intentional. - def unlock_tray(self, comingnext, is_showing_dlg=[False]): - if is_showing_dlg[0]: - return - - is_showing_dlg[0] = True - - entered_pass = gtk.Entry(25) - entered_pass.set_activates_default(True) - entered_pass.set_width_chars(25) - entered_pass.set_visibility(False) - entered_pass.show() - tray_lock = gtk.Dialog(title=_("Deluge is locked"), parent=self.window, - buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, - gtk.RESPONSE_ACCEPT)) - label = gtk.Label(_("Deluge is password protected.\nTo show the Deluge \ -window, please enter your password")) - label.set_line_wrap(True) - label.set_justify(gtk.JUSTIFY_CENTER) - tray_lock.set_position(gtk.WIN_POS_CENTER_ALWAYS) - tray_lock.set_size_request(400, 200) - tray_lock.set_default_response(gtk.RESPONSE_ACCEPT) - tray_lock.vbox.pack_start(label) - tray_lock.vbox.pack_start(entered_pass) - tray_lock.show_all() - if tray_lock.run() == gtk.RESPONSE_ACCEPT: - import sha - #for backward compatibility - if len(self.config.get("tray_passwd")) != 40: - password = sha.new(self.config.get("tray_passwd")).hexdigest() - else: - password = self.config.get("tray_passwd") - if password == sha.new(entered_pass.get_text()).hexdigest(): - if comingnext == "mainwinshow": - self.window.show() - elif comingnext == "prefwinshow": - self.show_preferences_dialog() - elif comingnext == "plugwinshow": - self.show_plugin_dialog() - elif comingnext == "quitus": - self.shutdown() - - tray_lock.destroy() - - is_showing_dlg[0] = False - - return True - - def load_status_icons(self): - self.status_icons = \ - {'paused': gtk.gdk.pixbuf_new_from_file( - common.get_pixmap("inactive16.png")), - 'seeding': gtk.gdk.pixbuf_new_from_file( - common.get_pixmap("seeding16.png")), - 'downloading' : gtk.gdk.pixbuf_new_from_file( - common.get_pixmap("downloading16.png"))} - - def list_of_trackers(self, obj=None): - torrent = self.get_selected_torrent() - if torrent is not None: - trackerslist = self.manager.get_trackers(torrent) - self.show_edit_tracker_dialog(trackerslist) - - def cancel_edit_window(self, arg=None): - self.edit_window.destroy() - - def accept_edit_window(self, arg=None): - torrent = self.get_selected_torrent() - self.textlist = self.textbuffer.get_text(self.textbuffer.\ - get_start_iter(), self.textbuffer.get_end_iter(), - include_hidden_chars=False).strip() - self.manager.replace_trackers(torrent, self.textlist) - self.edit_window.destroy() - - def show_edit_tracker_dialog(self, list): - self.textbuffer = gtk.TextBuffer(table=None) - self.textbuffer.set_text(list) - self.edit_glade = gtk.glade.XML(common.get_glade_file( - "edit_trackers.glade")) - self.edit_list = self.edit_glade.get_widget("txt_tracker_list") - self.edit_list.set_buffer(self.textbuffer) - self.edit_window = self.edit_glade.get_widget("edittrackers") - self.edit_window.set_position(gtk.WIN_POS_CENTER_ALWAYS) - self.edit_window.set_size_request(400, 200) - self.edit_glade.signal_autoconnect({ - "cancel_button_clicked": self.cancel_edit_window, - "ok_button_clicked": self.accept_edit_window - }) - - self.edit_window.show_all() - - return True - - def tray_clicked(self, status_icon): - if self.window.get_property("visible"): - if self.window.is_active(): - self.window.hide() - else: - # Force UI update as we don't update it while minimized - self.update() - self.window.present() - else: - if self.config.get("lock_tray"): - self.unlock_tray("mainwinshow") - else: - self.load_window_geometry() - self.window.show() - # Force UI update as we don't update it while in tray - self.update() - - def show_hide_window_toggled(self, widget): - if widget.get_active() and not self.window.get_property("visible"): - if self.config.get("lock_tray"): - self.unlock_tray("mainwinshow") - else: - self.window.show() - elif not widget.get_active() and self.window.get_property("visible"): - self.window.hide() - - def build_torrent_table(self): - ## Create the torrent listview - self.torrent_view = self.wtree.get_widget("torrent_view") - torrent_glade = gtk.glade.XML(common.get_glade_file( - "torrent_menu.glade"), domain='deluge') - torrent_glade.signal_autoconnect({ - "remove_torrent": self.remove_torrent_clicked, - "edit_trackers": self.list_of_trackers, - "tor_start": self.tor_start, - "torrent_switch_recheck": self.torrent_switch_recheck, - "tor_pause": self.tor_pause, - "update_tracker": self.update_tracker, - "clear_finished": self.clear_finished, - "open_folder_clicked": self.open_folder, - "queue_up": self.q_torrent_up, - "queue_down": self.q_torrent_down, - "queue_bottom": self.q_to_bottom, - "queue_top": self.q_to_top - }) - self.torrent_menu = torrent_glade.get_widget("torrent_menu") - # unique_ID, Q#, Status Icon, Name, Size, Progress, Message, Seeders, - # Peers, DL, UL, ETA, Share - self.torrent_model = gtk.ListStore(int, gobject.TYPE_UINT, - gtk.gdk.Pixbuf, str, gobject.TYPE_UINT64, float, str, int, int, - int, int, int, int, gobject.TYPE_UINT64, float, float) - # Stores unique_ID -> gtk.TreeRowReference's mapping for quick look up - self.torrent_model_dict = {} - - self.torrent_view.connect("row-activated", self.double_click_folder) - self.torrent_view.set_model(self.torrent_model) - self.torrent_view.set_rules_hint(True) - self.torrent_view.set_reorderable(True) - self.torrent_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE) - - def peer(column, cell, model, iter, data): - c1, c2 = data - a = model.get_value(iter, c1) - b = model.get_value(iter, c2) - cell.set_property('text', '%d (%d)'%(a, b)) - - def time(column, cell, model, iter, data): - time = model.get_value(iter, data) - if time < 0 or time == 0: - time_str = _("Infinity") - else: - time_str = common.ftime(time) - cell.set_property('text', time_str) - - def availability(column, cell, model, iter, data): - availability_str = model.get_value(iter, data) - cell.set_property('text', "%.3f" % availability_str) - - def ratio(column, cell, model, iter, data): - ratio = model.get_value(iter, data) - if ratio == -1: - ratio_str = _("Unknown") - else: - ratio_str = "%.3f" % ratio - cell.set_property('text', ratio_str) - - ## Initializes the columns for the torrent_view - (TORRENT_VIEW_COL_UID, TORRENT_VIEW_COL_QUEUE, - TORRENT_VIEW_COL_STATUSICON, TORRENT_VIEW_COL_NAME, - TORRENT_VIEW_COL_SIZE, TORRENT_VIEW_COL_PROGRESS, - TORRENT_VIEW_COL_STATUS, TORRENT_VIEW_COL_CONNECTED_SEEDS, - TORRENT_VIEW_COL_SEEDS, TORRENT_VIEW_COL_CONNECTED_PEERS, - TORRENT_VIEW_COL_PEERS, TORRENT_VIEW_COL_DOWNLOAD, - TORRENT_VIEW_COL_UPLOAD, TORRENT_VIEW_COL_ETA, - TORRENT_VIEW_COL_AVAILABILITY, TORRENT_VIEW_COL_RATIO) = range(16) - - self.queue_column = dgtk.add_text_column(self.torrent_view, "#", - TORRENT_VIEW_COL_QUEUE, width=self.config.get("queue_width")) - self.name_column = dgtk.add_texticon_column(self.torrent_view, _("Name"\ - ), TORRENT_VIEW_COL_STATUSICON, TORRENT_VIEW_COL_NAME, width=\ - self.config.get("name_width")) - self.size_column = dgtk.add_func_column(self.torrent_view, _("Size"), \ - dgtk.cell_data_size, TORRENT_VIEW_COL_SIZE, width=self.config.get\ - ("size_width")) - self.status_column = dgtk.add_progress_column(self.torrent_view, _(\ - "Status"), TORRENT_VIEW_COL_PROGRESS, TORRENT_VIEW_COL_STATUS, - width=self.config.get("status_width")) - self.seed_column = dgtk.add_func_column(self.torrent_view, _("Seeders")\ - , peer, (TORRENT_VIEW_COL_CONNECTED_SEEDS, TORRENT_VIEW_COL_SEEDS)\ - , width=self.config.get("seed_width")) - self.peer_column = dgtk.add_func_column(self.torrent_view, _("Peers"), \ - peer, (TORRENT_VIEW_COL_CONNECTED_PEERS, TORRENT_VIEW_COL_PEERS), \ - width=self.config.get("peer_width")) - self.dl_column = dgtk.add_func_column(self.torrent_view, _("Down Speed"\ - ), dgtk.cell_data_speed, TORRENT_VIEW_COL_DOWNLOAD, width=\ - self.config.get("dl_width")) - self.ul_column = dgtk.add_func_column(self.torrent_view, _("Up Speed"), - dgtk.cell_data_speed, TORRENT_VIEW_COL_UPLOAD, width=\ - self.config.get("ul_width")) - self.eta_column = dgtk.add_func_column(self.torrent_view, _("ETA"), - time, TORRENT_VIEW_COL_ETA, width=self.config.get("eta_width")) - self.availability_column = dgtk.add_func_column(self.torrent_view, - _("Avail."), availability, TORRENT_VIEW_COL_AVAILABILITY, width=\ - self.config.get("availability_width")) - self.share_column = dgtk.add_func_column(self.torrent_view, _("Ratio"), - ratio, TORRENT_VIEW_COL_RATIO, width=self.config.get("share_width")) - - self.name_column.set_sort_column_id(TORRENT_VIEW_COL_NAME) - self.seed_column.set_sort_column_id(TORRENT_VIEW_COL_CONNECTED_SEEDS) - self.peer_column.set_sort_column_id(TORRENT_VIEW_COL_CONNECTED_PEERS) - - self.torrent_model.set_sort_column_id(TORRENT_VIEW_COL_QUEUE, - gtk.SORT_ASCENDING) - try: - self.torrent_view.get_selection().set_select_function( - self.torrent_clicked, full=True) - except TypeError: - self.torrent_view.get_selection().set_select_function( - self.old_t_click) - self.torrent_view.connect("button-press-event", - self.torrent_view_clicked) - - def torrent_model_append(self, unique_id): - state = self.manager.get_torrent_state(unique_id) - iter = self.torrent_model.append( - self.get_torrent_state_list(unique_id, state)) - path = self.torrent_model.get_string_from_iter(iter) - row_ref = gtk.TreeRowReference(self.torrent_model, path) - - self.torrent_model_dict[unique_id] = row_ref - - def torrent_model_remove(self, unique_id): - row_ref = self.torrent_model_dict[unique_id] - iter = self.torrent_model.get_iter(row_ref.get_path()) - self.torrent_model.remove(iter) - - del self.torrent_model_dict[unique_id] - - def old_t_click(self, path): - return self.torrent_clicked(self.torrent_view.get_selection(), - self.torrent_model, path, False) - - def torrent_clicked(self, selection, model, path, is_selected): - if is_selected: - # Torrent is already selected, we don't need to do anything - return True - - # We don't call update function directly, because torrent_clicked() - # called by GTK when torrent is not selected yet(read docs on - # gtk.TreeSelection.set_select_function()), but update routines - # expect already selected torrent. So queue update functions until we - # exit from torrent_clicked() and torrent will be actually selected by - # the time update functions called. Hope 10ms will be always enough - # for this. - gobject.timeout_add(10, self.update_torrent_info_widget) - gobject.timeout_add(10, self.plugins.update_active_plugins) - - return True - - def torrent_view_clicked(self, widget, event): - if event.button == 3: - data = self.torrent_view.get_path_at_pos(int(event.x), int(event.y)) - if data is None: - return True - - path = data[0] - is_selected = self.torrent_view.get_selection().path_is_selected\ - (path) - if not is_selected: - self.torrent_view.grab_focus() - self.torrent_view.set_cursor(path) - - self.torrent_menu.popup(None, None, None, event.button, - event.time) - - return is_selected - else: - return False - - def double_click_folder(self, tree, path, view_column): - self.open_folder(view_column) - - def open_folder(self, widget, uids=None): - if not uids: - unique_ids = self.get_selected_torrent_rows() - else: - unique_ids = uids - - try: - for uid in unique_ids: - torrent_path = self.manager.get_torrent_path(uid) - if not common.windows_check(): - file_manager = "xdg-open" - else: - file_manager = "explorer.exe" - common.exec_command(file_manager, torrent_path) - - except KeyError: - pass - - def torrent_switch_recheck(self, widget=None, switch=False): - unique_ids = self.get_selected_torrent_rows() - for uid in unique_ids: - torrent_state = self.manager.get_torrent_state(uid) - order = torrent_state['queue_pos'] - path = self.manager.unique_IDs[uid].filename - if not switch: - save_dir = self.manager.unique_IDs[uid].save_dir - delete_old = False - else: - save_dir = dialogs.show_directory_chooser_dialog(self.window, \ - _("Choose a directory to switch torrent source to" + " - %s" % \ - self.manager.get_torrent_state(uid)['name'])) - if save_dir: - delete_old = dialogs.show_popup_question(self.window, \ - _("Delete the old torrent source?")) - else: - delete_old = False - if save_dir: - trackerslist = self.manager.unique_IDs[uid].trackers - try: - trackers_changed = self.manager.unique_IDs[uid].trackers_changed - except AttributeError: - trackers_changed = 0 - self.manager.pickle_state() - uploaded_memory = self.manager.unique_IDs[uid].uploaded_memory - uploaded_memory += self.manager.get_core_torrent_state(uid, False)['total_payload_upload'] - priorities = self.manager.get_priorities(uid) - save_info = [path, save_dir, order, trackerslist, \ - uploaded_memory, priorities, trackers_changed, \ - delete_old] - try: - os.remove(self.manager.unique_IDs[uid].filename + ".fastresume") - except: - pass - if save_info[7]: - self.manager.remove_torrent(uid, True, False) - else: - self.manager.remove_torrent(uid, False, False) - self.torrent_model_remove(uid) - self.update() - unique_ID = self.manager.add_torrent(save_info[0], save_info[1], \ - self.config.get("use_compact_storage")) - self.torrent_model_append(unique_ID) - self.update() - self.manager.prioritize_files(unique_ID, save_info[5], update_files_removed=False) - if save_info[4]: - self.manager.unique_IDs[unique_ID].uploaded_memory = \ - save_info[4] - self.manager.pickle_state() - if save_info[6]: - try: - self.manager.replace_trackers(unique_ID, save_info[3]) - except: - pass - torrent_state = self.manager.get_torrent_state(unique_ID) - current_order = torrent_state['queue_pos'] - if current_order > save_info[2]: - diff = current_order - save_info[2] - for x in range(diff): - self.manager.queue_up(unique_ID) - self.update() - else: - diff = save_info[2] - current_order - for x in range(diff): - self.manager.queue_down(unique_ID) - self.update() - - def tor_start(self, widget): - unique_ids = self.get_selected_torrent_rows() - try: - for uid in unique_ids: - torrent_state = self.manager.get_torrent_state(uid) - if torrent_state["is_paused"]: - self.manager.set_user_pause(uid, False, True) - - self.update() - - except KeyError: - pass - - def tor_pause(self, widget): - try: - unique_ids = self.get_selected_torrent_rows() - for uid in unique_ids: - self.manager.set_user_pause(uid, True, True) - torrent_state = self.manager.get_torrent_state(uid) - self.update() - except: - pass - - def show_about_dialog(self, arg=None): - dialogs.show_about_dialog(self.window) - - def run_wizard(self, arg=None): - import wizard - wizard.WizardGTK() - #reload config file - import pref - self.config = pref.Preferences(os.path.join(common.CONFIG_DIR, "prefs.state")) - self.apply_prefs() - - def show_preferences_dialog(self): - active_port = self.manager.get_state()['port'] - preferences_dialog = dialogs.PreferencesDlg(self.config, active_port, - self.plugins) - preferences_dialog.show(self, self.window) - - def show_preferences_dialog_clicked(self, arg=None): - if self.config.get("enable_system_tray") and \ - self.config.get("lock_tray") and not self.window.get_property( - "visible"): - self.unlock_tray("prefwinshow") - else: - self.show_preferences_dialog() - - def show_plugin_dialog(self, plugin_tab=True): - active_port = self.manager.get_state()['port'] - plugin_dialog = dialogs.PreferencesDlg(self.config, active_port, \ - self.plugins, plugin_tab=True) - plugin_dialog.show(self, self.window) - - def show_plugin_dialog_clicked(self, arg=None): - if self.config.get("enable_system_tray") and self.config.get( - "lock_tray") and not self.window.get_property("visible"): - self.unlock_tray("plugwinshow") - else: - self.show_plugin_dialog(plugin_tab=True) - - def apply_prefs(self): - # Show tray icon if necessary - self.tray_icon.set_visible(self.config.get("enable_system_tray")) - - # Update the max_*_speed_bps prefs - if self.config.get("max_upload_speed") < 0: - self.config.set("max_upload_speed_bps", -1) - else: - self.config.set("max_upload_speed_bps", - int(self.config.get("max_upload_speed") * 1024)) - - if self.config.get("max_download_speed") < 0: - self.config.set("max_download_speed_bps", -1) - else: - self.config.set("max_download_speed_bps", - int(self.config.get("max_download_speed") * 1024)) - - # Update the tray download speed limits - if self.config.get("max_download_speed") not in self.config.get( - "tray_downloadspeedlist") and self.config.get("max_download_speed")\ - >= 0: - # We prepend this value and remove the last value in the list - self.config.get("tray_downloadspeedlist").insert(0, self.config.get( - "max_download_speed")) - self.config.get("tray_downloadspeedlist").pop() - - # Do the same for the upload speed limits - if self.config.get("max_upload_speed") not in self.config.get( - "tray_uploadspeedlist") and self.config.get("max_upload_speed") >= \ - 0: - # We prepend this value and remove the last value in the list - self.config.get("tray_uploadspeedlist").insert(0, self.config.get( - "max_upload_speed")) - self.config.get("tray_uploadspeedlist").pop() - - # Re-build the tray sub-menu to display the correct active radio item - self.build_tray_bwsetsubmenu() - - # Apply the preferences in the core - self.manager.apply_prefs() - self.manager.pe_settings(self.config.get("encout_state"), - self.config.get("encin_state"), self.config.get("enclevel_type"), - self.config.get("pref_rc4")) - if self.config.get("peer_proxy"): - self.manager.proxy_settings(self.config.get("peer_proxy_hostname"), - self.config.get("peer_proxy_username"), self.config.get( - "peer_proxy_password"), - int(self.config.get("peer_proxy_port")), self.config.get( - "peer_proxy_type"), "peer") - if self.config.get("dht_proxy"): - self.manager.proxy_settings(self.config.get("dht_proxy_hostname"), - self.config.get("dht_proxy_username"), self.config.get( - "dht_proxy_password"), - int(self.config.get("dht_proxy_port")), self.config.get( - "dht_proxy_type"), "dht") - if self.config.get("tracker_proxy"): - self.manager.proxy_settings(self.config.get( - "tracker_proxy_hostname"), - self.config.get("tracker_proxy_username"), self.config.get( - "tracker_proxy_password"), - int(self.config.get("tracker_proxy_port")), self.config.get( - "tracker_proxy_type"), "tracker") - if self.config.get("web_proxy"): - self.manager.proxy_settings(self.config.get("web_proxy_hostname"), - self.config.get("web_proxy_username"), self.config.get( - "web_proxy_password"), - int(self.config.get("web_proxy_port")), self.config.get( - "web_proxy_type"), "web") - - def get_message_from_state(self, unique_id, torrent_state): - state = torrent_state['state'] - is_paused = torrent_state['is_paused'] - progress = torrent_state['progress'] - progress = '%d%%' % (progress * 100) - if is_paused: - if self.manager.is_user_paused(unique_id): - message = _("Paused %s") % progress - else: - message = _("Queued %s") % progress - else: - try: - message = core.STATE_MESSAGES[state] - if state in (1, 3, 4, 7): - message = '%s %s' % (message, progress) - except IndexError: - message = '' - return message - - # UID, Q#, Name, Size, Progress, Message, Seeders, Peers, DL, UL, ETA, - # Share - def get_torrent_state_list(self, unique_id, state): - queue = state['queue_pos'] - name = state['name'] - size = state['total_wanted'] - progress = state['progress'] * 100 - message = self.get_message_from_state(unique_id, state) - availability = state['distributed_copies'] - share = self.manager.calc_ratio(unique_id, state) - - # setting after initial paused state ensures first change gets updated - if state["is_paused"]: - # Update stats to pause state immediately so interface does not - # need to keep updating when paused - seeds = seeds_t = peers = peers_t = dl_speed = ul_speed = eta = 0 - # Set status icon as pause - status_icon = self.status_icons['paused'] - else: - seeds = state['num_seeds'] - seeds_t = state['total_seeds'] - peers = state['num_peers'] - peers_t = state['total_peers'] - dl_speed = int(state['download_rate']) - ul_speed = int(state['upload_rate']) - try: - eta = common.get_eta(size, state["total_wanted_done"], - dl_speed) - except ZeroDivisionError: - eta = 0 - # Set the appropriate status icon - if state["is_seed"] or \ - state["state"] == self.manager.constants["STATE_FINISHED"]: - status_icon = self.status_icons['seeding'] - else: - status_icon = self.status_icons['downloading'] - - rlist = [unique_id, queue, status_icon, name, size, progress, - message, seeds, seeds_t, peers, peers_t, dl_speed, ul_speed, - eta, availability, share] - - return rlist - - ## Start the timer that updates the interface - def start(self, cmd_line_torrents=None): - if cmd_line_torrents is None: - cmd_line_torrents = [] - if not(self.config.get("start_in_tray") and \ - self.config.get("enable_system_tray") and - self.has_tray) and not self.window.get_property("visible"): - print "Showing window" - self.window.show() - - ## add torrents in manager's queue to interface - for torrent in self.manager.get_queue(): - unique_id = self.manager.get_torrent_unique_id(torrent) - self.torrent_model_append(unique_id) - - for torrent_file in cmd_line_torrents: - self.interactive_add_torrent(torrent_file) - - # Call update now so everything is up-to-date when the window gains - # focus on startup - self.update() - gobject.timeout_add(int(1000*self.manager.config.get("gui_update_interval")), self.update) - gobject.timeout_add(250000, self.manager.pickle_state) - gobject.timeout_add(300000, self.manager.save_fastresume_data) - - # Load plugins after we showed main window (if not started in tray) - self.load_plugins() - self.load_tabs_order() - if self.config.get("new_releases"): - self.new_release_check() - - try: - gobject.threads_init() - gtk.gdk.threads_enter() - gtk.main() - gtk.gdk.threads_leave() - except KeyboardInterrupt: - self.shutdown() - - def new_release_check(self): - import socket - import urllib - timeout = 5 - socket.setdefaulttimeout(timeout) - try: - gtk.gdk.threads_enter() - except: - pass - try: - new_release = urllib.urlopen("http://download.deluge-torrent.org/version").read().strip() - except IOError: - print "Network error while trying to check for a newer version of \ -Deluge" - try: - gtk.gdk.threads_leave() - except: - pass - return - - if new_release > common.PROGRAM_VERSION: - result = dialogs.show_popup_question(None, _("There is a newer version \ -of Deluge. Would you like to be taken to our download site?")) - if result: - common.open_url_in_browser('http://download.deluge-torrent.org/') - else: - pass - try: - gtk.gdk.threads_leave() - except: - pass - - def load_plugins(self): - enable_plugins = self.config.get('enabled_plugins').split(':') - for plugin in enable_plugins: - if plugin != "Blocklist Importer" and plugin != "Torrent Pieces" and plugin != "FlexRSS": - try: - self.plugins.enable_plugin(plugin) - except KeyError: - pass - if "Blocklist Importer" in enable_plugins: - self.plugins.enable_plugin("Blocklist Importer") - if "FlexRSS" in enable_plugins: - self.plugins.enable_plugin("FlexRSS") - - ## Call via a timer to update the interface - def update(self): - if self.config.get("autoload") and self.config.get("default_autoload_path"): - try: - for filename in os.listdir(self.config.get("default_autoload_path")): - if filename[-len(".torrent"):].lower() == ".torrent": - self.interactive_add_torrent_path(os.path.join(\ - self.config.get("default_autoload_path"), filename), \ - self.config.get("default_download_path")) - os.remove(os.path.join(self.config.get("default_autoload_path"), filename)) - except: - pass - # Handle the events - self.manager.handle_events() - - # We need to apply the queue changes - self.manager.apply_queue() - - self.update_interface = self.window.get_property("visible") and not \ - self.is_minimized - - # Make sure that the interface still exists - try: - self.wtree.get_widget("torrent_info").get_current_page() - except AttributeError: - return False - - # Update Statusbar and Tray Tips - self.update_statusbar_and_tray() - - #Update any active plugins - self.plugins.update_active_plugins() - - #Plugins have updated info, so clear it - self.manager.clear_update_files_removed() - - # only update gui if it's needed - if self.update_interface: - # Put the generated message into the statusbar - # This gives plugins a chance to write to the - # statusbar if they want - self.statusbar.pop(1) - self.statusbar.push(1, self.statusbar_temp_msg) - - #Torrent List - itr = self.torrent_model.get_iter_first() - - # Disable torrent options if there are no torrents - self.wtree.get_widget("menu_torrent").set_sensitive(itr is not None) - self.wtree.get_widget("toolbutton_clear").set_sensitive(itr is not None) - self.wtree.get_widget("toolbutton_remove").set_sensitive(itr is \ - not None) - self.wtree.get_widget("toolbutton_resume").set_sensitive(itr is \ - not None) - self.wtree.get_widget("toolbutton_pause").set_sensitive(itr is \ - not None) - if len(self.manager.get_queue()) > 1: - self.wtree.get_widget("toolbutton_up").set_sensitive(True) - self.wtree.get_widget("toolbutton_down").set_sensitive(True) - else: - self.wtree.get_widget("toolbutton_up").set_sensitive(False) - self.wtree.get_widget("toolbutton_down").set_sensitive(False) - - if itr is None: - return True - - while itr is not None: - unique_id = self.torrent_model.get_value(itr, 0) - - if unique_id in self.manager.removed_unique_ids: - selected_unique_id = self.get_selected_torrent() - # If currently selected torrent was complete and so - # removed clear details pane - if selected_unique_id == unique_id: - self.clear_details_pane() - - next = self.torrent_model.iter_next(itr) - self.torrent_model.remove(itr) - itr = self.torrent_model.get_iter_first() - if itr is None: - return True - itr = next - - del self.manager.removed_unique_ids[unique_id] - continue - - # self.torrent_model holds previous state of the torrent. - # We can check by icon was it paused or not. - previosly_paused = self.torrent_model.get_value(itr, 2) == \ - self.status_icons['paused'] - state = self.manager.get_torrent_state(unique_id) - if previosly_paused and state['is_paused']: - # For previosly and still paused torrents update only - # queue pos, selected files size and status message. - # All the other columns are unchanged. - message = self.get_message_from_state(unique_id, state) - dgtk.update_store(self.torrent_model, itr, (1, 4, 6), - (state['queue_pos'], - state['total_wanted'], - message)) - else: - tlist = self.get_torrent_state_list(unique_id, state) - dgtk.update_store(self.torrent_model, itr, - xrange(len(tlist)), tlist) - - itr = self.torrent_model.iter_next(itr) - torrent_selection = self.torrent_view.get_selection() - selection_count = torrent_selection.count_selected_rows() - - # If no torrent is selected, select the first torrent: - if selection_count == 0: - torrent_selection.select_path("0") - selection_count = 1 - - if selection_count == 1: - self.update_torrent_info_widget() - else: # selection_count > 1 - self.clear_details_pane() - - return True - - def update_statusbar_and_tray(self): - plugin_messages = self.plugins.get_plugin_tray_messages() - core_state = self.manager.get_state() - connections = core_state['num_connections'] - if self.config.get("max_connections_global") < 0 : - max_connections = _("Unlimited") - else: - max_connections = self.config.get("max_connections_global") - dlspeed = common.fspeed(core_state['download_rate']) - ulspeed = common.fspeed(core_state['upload_rate']) - - if self.config.get("max_download_speed") < 0: - dlspeed_max = _("Unlimited") - else: - dlspeed_max = common.fspeed(self.config.get( - "max_download_speed_bps")) - if self.config.get("max_upload_speed") < 0: - ulspeed_max = _("Unlimited") - else: - ulspeed_max = common.fspeed(self.config.get("max_upload_speed_bps")) - - # Use self.statusbar_temp_msg instance var to allow plugins access it - self.statusbar_temp_msg = '%s: %s (%s) %s: %s (%s) %s: %s (%s)' % ( - _("Connections"), connections, max_connections, _("Down Speed"), - dlspeed, dlspeed_max, _("Up Speed"), ulspeed, ulspeed_max) - - if 'DHT_nodes' in core_state: - dht_peers = core_state['DHT_nodes'] - if dht_peers == -1: - dht_peers = '?' - if dht_peers == 0: - self.dht_timer += 1 - if (self.dht_timer == 20) and (self.manager.\ - get_state()['num_peers'] > 0) and (not self.dht_skip): - self.manager.set_DHT(False) - os.remove(common.CONFIG_DIR + '/dht.state') - self.manager.set_DHT(True) - self.dht_skip = True - else: - dht_peers = str(dht_peers) - self.statusbar_temp_msg = self.statusbar_temp_msg + \ - ' [' + _("DHT") + ': %s]'%(dht_peers) - # windows cant display more than 64 characters in systray tooltip - if common.windows_check(): - #msg = _("Deluge Bittorrent Client") - if ulspeed_max == _("Unlimited"): - ulspeed_max = "*" - if dlspeed_max == _("Unlimited"): - dlspeed_max = "*" - msg = '%s\n%s: %s (%s)\n%s: %s (%s)' % (\ - _("Deluge"), _("Download"), dlspeed, \ - dlspeed_max, _("Upload"), ulspeed, ulspeed_max) - else: - msg = '%s\n%s: %s (%s)\n%s: %s (%s)%s' % (\ - _("Deluge Bittorrent Client"), _("Down Speed"), dlspeed, \ - dlspeed_max, _("Up Speed"), ulspeed, ulspeed_max, plugin_messages) - - self.tray_icon.set_tooltip(msg) - - def update_torrent_info_widget(self): - unique_id = self.get_selected_torrent() - # If no torrents added - if unique_id is None: - return - - page_num = self.wtree.get_widget("torrent_info").get_current_page() - - if page_num == 0: # Details - self.tab_details.update(unique_id) - - # We have to return False here to stop calling this function by timer - # over and over again, from self.torrent_clicked() for example. - return False - - # Return the id of the last single selected torrent - def get_selected_torrent(self): - try: - if self.torrent_view.get_selection().count_selected_rows() == 1: - selected_path = self.torrent_view.get_selection().\ - get_selected_rows()[1][0] - selected_torrent = self.torrent_model.get_value( - self.torrent_model.get_iter(selected_path), 0) - return selected_torrent - except (TypeError, ValueError): - pass - - return None - - # Return a list of ids of the selected torrents - def get_selected_torrent_rows(self): - selected_ids = [] - selected_paths = self.torrent_view.get_selection().get_selected_rows()\ - [1] - - try: - for path in selected_paths: - selected_ids.append(self.torrent_model.get_value( - self.torrent_model.get_iter(path), 0)) - return selected_ids - except ValueError: - return None - - def on_drag_data(self, widget, drag_context, x, y, selection_data, info, - timestamp): - import urllib - - uri_split = selection_data.data.strip().split() - for uri in uri_split: - if uri.startswith('file://') and common.windows_check(): - uri = uri[7:] - path = urllib.url2pathname(uri).strip('\r\n\x00') - if path.startswith('file:\\\\\\'): - path = path[8:] - elif path.startswith('file://'): - path = path[7:] - elif path.startswith('file:'): - path = path[5:] - if path.endswith('.torrent'): - self.interactive_add_torrent(path) - - def interactive_add_torrent_url(self, url): - if url: - filename = common.fetch_url(url) - if filename: - return self.interactive_add_torrent(filename) - - def interactive_add_torrent(self, torrent): - if self.config.get('use_default_dir'): - path = self.config.get('default_download_path') - else: - path = dialogs.show_directory_chooser_dialog(self.window, - _("Choose a download directory")) - if path is None: - return - - return self.interactive_add_torrent_path(torrent, path) - - def interactive_add_torrent_path(self, torrent, path): - unique_id = False - - try: - dumped_torrent = self.manager.dump_torrent_file_info(torrent) - if self.config.get('enable_files_dialog') and not \ - self.config.get('enable_multi_only'): - files_dialog = dialogs.FilesDlg(dumped_torrent) - if files_dialog.show(self.window) == 1: - unique_id = self.manager.add_torrent(torrent, path, - self.config.get('use_compact_storage'), \ - self.config.get('start_paused')) - self.manager.prioritize_files(unique_id, - files_dialog.get_priorities()) - if files_dialog.is_private_flag_checked(): - self.manager.set_priv(unique_id, True) - else: - return False - elif self.config.get('enable_files_dialog') and \ - self.config.get('enable_multi_only') and (len(dumped_torrent) > 1): - files_dialog = dialogs.FilesDlg(dumped_torrent) - if files_dialog.show(self.window) == 1: - unique_id = self.manager.add_torrent(torrent, path, - self.config.get('use_compact_storage'), \ - self.config.get('start_paused')) - self.manager.prioritize_files(unique_id, - files_dialog.get_priorities()) - if files_dialog.is_private_flag_checked(): - self.manager.set_priv(unique_id, True) - else: - return False - elif self.config.get('enable_files_dialog') and \ - self.config.get('enable_multi_only') and not (len(dumped_torrent) > 1): - unique_id = self.manager.add_torrent(torrent, path, - self.config.get('use_compact_storage'), \ - self.config.get('start_paused')) - - elif not self.config.get('enable_files_dialog'): - unique_id = self.manager.add_torrent(torrent, path, - self.config.get('use_compact_storage'), \ - self.config.get('start_paused')) - except core.InvalidEncodingError, e: - print "InvalidEncodingError", e - dialogs.show_popup_warning(self.window, _("An error occured while \ -trying to add the torrent. It's possible your .torrent file is corrupted.")) - except core.DuplicateTorrentError, e: - for unique_id in self.manager.unique_IDs: - is_duplicate = self.manager.test_duplicate(torrent, unique_id) - if is_duplicate: - break - if is_duplicate: - merge_dialog = dialogs.MergeDlg() - if merge_dialog.show(self.window) == 1: - new_trackers_as_list = self.manager.dump_trackers(torrent)\ - .splitlines() - original_trackers_as_list = self.manager.get_trackers( - unique_id).splitlines() - merged_trackers = [] - for s in original_trackers_as_list, new_trackers_as_list: - for x in s: - merged_trackers.append(x) - #remove duplicates - d = {} - for k in merged_trackers: - d[k] = 1 - merged_trackers_as_string = '' - for x in d.keys(): - merged_trackers_as_string = merged_trackers_as_string + x + '\n' - self.manager.replace_trackers(unique_id, - merged_trackers_as_string.strip()) - else: - dialogs.show_popup_warning(self.window, _("Unknown duplicate \ -torrent error.")) - except core.InsufficientFreeSpaceError, e: - nice_need = common.fsize(e.needed_space) - nice_free = common.fsize(e.free_space) - dialogs.show_popup_warning(self.window, _("There is not enough free\ -disk space to complete your download.") + "\n" + _("Space Needed:") + " " + \ -nice_need + "\n" + _("Available Space:") + " " + nice_free) - except core.InvalidEncodingError, e: - print "invalid encoding\n" - except Exception, e: - print "Unable to add torrent:", e - else: - self.torrent_model_append(unique_id) - - return unique_id - - def launchpad(self, obj=None): - common.open_url_in_browser('https://translations.launchpad.net/deluge/\ -trunk/+pots/deluge') - - def launch_faq(self, obj=None): - common.open_url_in_browser('http://deluge-torrent.org/faq.php') - - def launch_donate(self, obj=None): - common.open_url_in_browser('http://deluge-torrent.org/downloads.php') - - def launch_community(self, obj=None): - common.open_url_in_browser('http://forum.deluge-torrent.org/') - - def launch_homepage(self, obj=None): - common.open_url_in_browser('http://deluge-torrent.org/') - - def add_torrent_clicked(self, obj=None): - torrent = dialogs.show_file_open_dialog(self.window) - if torrent is not None: - for single in torrent: - self.interactive_add_torrent(single) - - def add_torrent_url_clicked(self, obj=None): - dlg = gtk.Dialog(_("Add torrent from URL"), self.window, 0, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,gtk.STOCK_OK, gtk.RESPONSE_OK)) - dlg.set_default_response(gtk.RESPONSE_OK) - dlg.set_icon(common.get_logo(18)) - label = gtk.Label(_("Enter the URL of the .torrent to download")) - entry = gtk.Entry() - entry.connect("activate", lambda w : dlg.response(gtk.RESPONSE_OK)) - dlg.vbox.pack_start(label) - dlg.vbox.pack_start(entry) - if common.windows_check(): - import win32clipboard as clip - import win32con - clip.OpenClipboard() - text=clip.GetClipboardData(win32con.CF_UNICODETEXT) - clip.CloseClipboard() - else: - clip = gtk.clipboard_get(selection='PRIMARY') - text = clip.wait_for_text() - if text: - text = text.strip() - if common.is_url(text): - entry.set_text(text) - dlg.show_all() - response = dlg.run() - if response == gtk.RESPONSE_OK: - url = entry.get_text().decode("utf_8") - dlg.destroy() - self.interactive_add_torrent_url(url) - else: - dlg.destroy() - - def remove_torrent_clicked(self, obj=None): - glade = gtk.glade.XML(common.get_glade_file("dgtkpopups.glade"), - domain='deluge') - asker = glade.get_widget("remove_torrent_dlg") - if not common.windows_check(): - asker.set_icon(common.get_logo(18)) - asker.set_transient_for(self.window) - - warning = glade.get_widget("warning") - warning.set_text(" ") - - torrent_also = glade.get_widget("torrent_also") - data_also = glade.get_widget("data_also") - data_also.connect("toggled", self.remove_toggle_warning, warning) - - response = asker.run() - asker.destroy() - if response == 1: - self.clear_details_pane() - - unique_ids = self.get_selected_torrent_rows() - - for unique_id in unique_ids: - self.manager.remove_torrent(unique_id, data_also.get_active(), - torrent_also.get_active()) - self.torrent_model_remove(unique_id) - - self.update() - - def clear_details_pane(self): - self.tab_details.clear() - - def remove_toggle_warning(self, args, warning): - if not args.get_active(): - warning.set_text(" ") - else: - warning.set_markup("" + _("Warning - all downloaded files for \ -this torrent will be deleted!") + "") - return False - - def update_tracker(self, obj=None): - unique_ids = self.get_selected_torrent_rows() - for uid in unique_ids: - self.manager.update_tracker(uid) - - def scrape_tracker(self, obj=None): - unique_ids = self.get_selected_torrent_rows() - for uid in unique_ids: - self.manager.scrape_tracker(uid) - - def clear_finished(self, obj=None): - print "Clearing completed torrents" - if dialogs.show_popup_question(self.window, _("Are you sure that you \ -want to remove all seeding torrents?")): - self.manager.clear_completed() - self.update() - - def select_all_torrents(self, widget): - self.torrent_view.get_selection().select_all() - - def q_torrent_up(self, obj=None): - for torrent in self.get_selected_torrent_rows(): - self.manager.queue_up(torrent) - self.update() - - def q_torrent_down(self, obj=None): - for torrent in reversed(self.get_selected_torrent_rows()): - self.manager.queue_down(torrent) - self.update() - - def q_to_bottom(self, widget): - for torrent in self.get_selected_torrent_rows(): - self.manager.queue_bottom(torrent) - self.update() - - def q_to_top(self, widget): - for torrent in reversed(self.get_selected_torrent_rows()): - self.manager.queue_top(torrent) - self.update() - - def toolbar_toggle(self, widget): - if widget.get_active(): - self.wtree.get_widget("tb_left").show() - else: - self.wtree.get_widget("tb_left").hide() - - def infopane_toggle(self, widget): - if widget.get_active(): - self.wtree.get_widget("torrent_info").show() - else: - self.wtree.get_widget("torrent_info").hide() - - def size_toggle(self, obj): - self.size_column.set_visible(obj.get_active()) - - - def status_toggle(self, obj): - self.status_column.set_visible(obj.get_active()) - - def seeders_toggle(self, obj): - self.seed_column.set_visible(obj.get_active()) - - def peers_toggle(self, obj): - self.peer_column.set_visible(obj.get_active()) - - def dl_toggle(self, obj): - self.dl_column.set_visible(obj.get_active()) - - def ul_toggle(self, obj): - self.ul_column.set_visible(obj.get_active()) - - def eta_toggle(self, obj): - self.eta_column.set_visible(obj.get_active()) - - def availability_toggle(self, obj): - self.availability_column.set_visible(obj.get_active()) - - def share_toggle(self, obj): - self.share_column.set_visible(obj.get_active()) - - def load_window_settings(self): - self.wtree.get_widget("chk_infopane").set_active(self.config.get( - "show_infopane")) - self.wtree.get_widget("chk_toolbar").set_active(self.config.get( - "show_toolbar")) - self.wtree.get_widget("chk_size").set_active(self.config.get( - "show_size")) - self.wtree.get_widget("chk_status").set_active(self.config.get( - "show_status")) - self.wtree.get_widget("chk_seed").set_active(self.config.get( - "show_seeders")) - self.wtree.get_widget("chk_peer").set_active(self.config.get( - "show_peers")) - self.wtree.get_widget("chk_download").set_active(self.config.get( - "show_dl")) - self.wtree.get_widget("chk_upload").set_active(self.config.get("show_ul")) - self.wtree.get_widget("chk_eta").set_active(self.config.get("show_eta")) - self.wtree.get_widget("chk_availability").set_active(self.config.get( - "show_availability")) - self.wtree.get_widget("chk_ratio").set_active(self.config.get( - "show_share")) - self.wtree.get_widget("vpaned1").set_position(self.config.get( - "window_height") - self.config.get("window_pane_position")) - - def save_window_settings(self): - self.config.set("show_infopane", self.wtree.get_widget("chk_infopane").\ - get_active()) - self.config.set("show_toolbar", self.wtree.get_widget("chk_toolbar").\ - get_active()) - self.config.set("show_size", self.wtree.get_widget("chk_size").\ - get_active()) - self.config.set("show_status", self.status_column.get_visible()) - self.config.set("show_seeders", self.seed_column.get_visible()) - self.config.set("show_peers", self.peer_column.get_visible()) - self.config.set("show_dl", self.dl_column.get_visible()) - self.config.set("show_ul", self.ul_column.get_visible()) - self.config.set("show_eta", self.eta_column.get_visible()) - self.config.set("show_availability", self.availability_column.\ - get_visible()) - self.config.set("show_share", self.share_column.get_visible()) - self.config.set("window_pane_position", self.config.get( - "window_height") - self.wtree.get_widget("vpaned1").get_position()) - - def save_column_widths(self): - to_save = ["queue", "name", "size", "status", "seed", "peer", "dl", - "ul", "eta", "availability", "share"] - for columns in to_save: - pref_name = columns + '_width' - column = getattr(self, columns + '_column') - self.config.set(pref_name, column.get_width()) - - # Saves the tabs order (except the 'Details' tab) - def save_tabs_order(self): - tabs_order = [] - num_tabs = self.notebook.get_n_pages() - for i in range(1, num_tabs): - tab = self.notebook.get_nth_page(i) - tabs_order.append(self.notebook.get_tab_label_text(tab)) - - tabs_order_str = ':'.join(tabs_order) - self.config.set('tabs_order', tabs_order_str) - - def load_tabs_order(self): - tabs_order_str = self.config.get('tabs_order') or "" - tabs_order = tabs_order_str.split(':') - tabs = {} - num_tabs = self.notebook.get_n_pages() - for i in range(1, num_tabs): - tab = self.notebook.get_nth_page(i) - tab_title = self.notebook.get_tab_label_text(tab) - tabs[tab_title] = tab - - i = 1 - for tab in tabs_order: - if tab in tabs: - self.notebook.reorder_child(tabs[tab], i) - i = i + 1 - - def window_configure_event(self, widget, event): - if not self.config.get("window_maximized"): - self.config.set("window_x_pos", self.window.get_position()[0]) - self.config.set("window_y_pos", self.window.get_position()[1]) - self.config.set("window_width", event.width) - self.config.set("window_height", event.height) - - def window_state_event(self, widget, event): - if event.changed_mask & gtk.gdk.WINDOW_STATE_MAXIMIZED: - if event.new_window_state & gtk.gdk.WINDOW_STATE_MAXIMIZED: - self.config.set("window_maximized", True) - else: - self.config.set("window_maximized", False) - if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED: - if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED: - self.is_minimized = True - else: - self.is_minimized = False - # Force UI update as we don't update it while minimized - self.update() - return False - - def load_window_geometry(self): - x = self.config.get('window_x_pos') - y = self.config.get('window_y_pos') - w = self.config.get('window_width') - h = self.config.get('window_height') - self.window.move(x, y) - self.window.resize(w, h) - if self.config.get("window_maximized"): - self.window.maximize() - - def close(self, widget, event): - if self.config.get("close_to_tray") and self.config.get( - "enable_system_tray") and self.has_tray: - self.window.hide() - return True - else: - self.quit() - - def quit(self, widget=None): - if self.window.get_property("visible"): - self.shutdown() - else: - if self.config.get("lock_tray"): - self.unlock_tray("quitus") - else: - self.shutdown() - - def shutdown(self, *arg): - gtk.quit_add(0, self.manager.quit) - self.window.hide() - self.save_column_widths() - self.save_window_settings() - self.save_tabs_order() - self.config.save() - self.plugins.shutdown_all_plugins() - #for the sake of windows, hide tray_icon - self.tray_icon.set_visible(False) - gtk.main_quit() - -## For testing purposes, create a copy of the interface -if __name__ == "__main__": - interface = DelugeGTK() - interface.start() diff --git a/src/ipc_manager.py b/src/ipc_manager.py deleted file mode 100644 index 95446749b..000000000 --- a/src/ipc_manager.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: utf-8 -*- -# ipc_manager.py -# -# Copyright (C) Zach Tibbitts 2006 -# -# 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 2, 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. - -import deluge._dbus as dbus -import dbus.service - -class Manager(dbus.service.Object): - def __init__(self, interface, object_path='/org/deluge_torrent/DelugeObject'): - self.interface = interface - self.bus = dbus.SessionBus() - bus_name = dbus.service.BusName("org.deluge_torrent.Deluge", bus=self.bus) - dbus.service.Object.__init__(self, bus_name, object_path) - - ## interactive_add_torrent should only be called from outside the class - @dbus.service.method('org.deluge_torrent.Deluge') - def interactive_add_torrent(self, torrent_file): - self.interface.interactive_add_torrent(torrent_file) diff --git a/src/plugins.py b/src/plugins.py deleted file mode 100644 index 6b5abf2e5..000000000 --- a/src/plugins.py +++ /dev/null @@ -1,151 +0,0 @@ -# -*- coding: utf-8 -*- -# -# delugeplugins.py -# -# Copyright (C) Zach Tibbitts 2006 -# -# 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 2, 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. - -import os -import sys -import imp - -class PluginManager: - def __init__(self, deluge_core, deluge_interface): - self.plugin_dirs = [] - self.available_plugins = {} - self.enabled_plugins = {} - self.core = deluge_core - self.interface = deluge_interface - - def add_plugin_dir(self, directory): - self.plugin_dirs.append(directory) - sys.path.append(directory) - - # Scans all defined plugin dirs for Deluge plugins. The resulting - # module object is store with the defined name. - def scan_for_plugins(self): - for folder in self.plugin_dirs: - print "Scanning plugin dir",folder - for modname in os.listdir(folder): - path = os.path.join(folder, modname) - if '__init__.py' in os.listdir(path): - # Import the found module. Note that the last - # parameter is important otherwise only the base - # modules (ie. 'plugins') is imported. This appears - # to be by design. - mod = __import__(modname, globals(), locals(), ['']) - if 'deluge_init' in dir(mod): - if (modname != "TorrentPieces") and (modname != "SimpleRSS") and (modname != "TorrentSearch"): - print "Initialising plugin", modname - try: - mod.deluge_init(path) - except: - print "Cant init plugin", modname - else: - self.available_plugins[mod.plugin_name] = mod - - def get_available_plugins(self): - return self.available_plugins.keys() - - def get_plugin(self, name): - return self.available_plugins[name] - - def enable_plugin(self, name): - plugin = self.available_plugins[name] - self.enabled_plugins[name] = plugin.enable(self.core, self.interface) - enabled_plugins = ':'.join(self.get_enabled_plugins()) - self.interface.config.set('enabled_plugins', enabled_plugins) - self.interface.config.save() - - def get_enabled_plugins(self): - return self.enabled_plugins.keys() - - def disable_plugin(self, name): - plugin = self.enabled_plugins[name] - if 'unload' in dir(plugin): - plugin.unload() - del self.enabled_plugins[name] - enabled_plugins = ':'.join(self.get_enabled_plugins()) - self.interface.config.set('enabled_plugins', enabled_plugins) - self.interface.config.save() - - def configurable_plugin(self, name): - if name in self.enabled_plugins: - return 'configure' in dir(self.enabled_plugins[name]) - else: - return False - - def configure_plugin(self, name, window): - self.enabled_plugins[name].configure(window) - - def launch_site(self, link): - self.enabled_plugins['Anonymizing Browser'].launch_site(link) - - def show_all(self): - self.enabled_plugins['Anonymizing Browser'].window.show_all() - - def get_plugin_tray_messages(self): - tray_message = "" - for name in self.enabled_plugins.keys(): - plugin = self.enabled_plugins[name] - if hasattr(plugin, 'get_tray_message'): - plugin_tray_message = plugin.get_tray_message() - if plugin_tray_message: - tray_message += '\n' + plugin_tray_message - - return tray_message - - def update_active_plugins(self): - for name in self.enabled_plugins.keys(): - plugin = self.enabled_plugins[name] - if 'update' in dir(plugin): - plugin.update() - - # We have to return False here to stop calling this function by timer - # over and over again, from interface.torrent_clicked() for example. - return False - - def shutdown_all_plugins(self): - for name in self.enabled_plugins.keys(): - plugin = self.enabled_plugins[name] - if 'unload' in dir(plugin): - plugin.unload() - del self.enabled_plugins[name] - self.enabled_plugins.clear() - - -## Few lines of code to test functionality -if __name__ == "__main__": - p = PluginManager() - p.add_plugin_dir("plugins/") - p.scan_for_plugins() - for x in p.plugins: - print x - for y in p.plugins[x]: - print "\t", y - diff --git a/src/pref.py b/src/pref.py deleted file mode 100644 index 3ffbdd9f1..000000000 --- a/src/pref.py +++ /dev/null @@ -1,365 +0,0 @@ -# -*- coding: utf-8 -*- -# pref.py -# -# Copyright (C) Zach Tibbitts 2006 -# -# 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 2, 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. - - -# Preferences is basically a wrapper around a simple Python dictionary -# object. However, this class provides a few extra features on top of -# the built in class that Deluge can take advantage of. - -import cPickle as pickle -import common -import os.path -import xdg - -if common.windows_check(): - DEFAULT_PREFS = { - "enabled_plugins" : "Torrent Files:Torrent Peers:Torrent Peers:Torrent Notification", - "file_manager" : common.FileManager.xdg, - "open_folder_stock" : True, - "send_redund" : False, - "autoload" : False, - "open_folder_location": "", - "send_info" : True, - "auto_end_seeding" : False, - "auto_time_end_seeding" : False, - "auto_seed_ratio" : 0, - "auto_seed_time" : 0, - "close_to_tray" : False, - "enable_files_dialog" : False, - "enable_multi_only" : True, - "queue_above_completed" : False, - "clear_max_ratio_torrents" : False, - "clear_max_time_torrents" : False, - "default_autoload_path" : os.path.expanduser("~"), - "default_torrent_path" : os.path.join(common.CONFIG_DIR, 'torrentfiles'), - "default_download_path" : os.path.expanduser("~"), - "open_torrent_dialog_path" : os.path.expanduser("~"), - "choose_directory_dialog_path": os.path.expanduser("~"), - "enable_dht" : True, - "enable_system_tray" : True, - "enabled_plugins" : "Torrent Files:Torrent Peers", - "encin_state" : common.EncState.enabled, - "encout_state" : common.EncState.enabled, - "enclevel_type" : common.EncLevel.both, - "end_seed_ratio" : 0.0, - "gui_update_interval" : 1.0, - "listen_on" : [6881,6889], - "lock_tray" : False, - "max_half_open" : 3, - "connection_speed" : -1, - "max_active_torrents" : 8, - "max_active_torrents_tmp" : 8, - "max_connections_global" : 200, - "max_connections_per_torrent" : -1, - "max_download_speed" : -1, - "max_download_speed_bps": -1, - "max_upload_slots_global" : 4, - "max_upload_slots_per_torrent" : -1, - "max_upload_speed" : -1, - "max_upload_speed_bps" : -1, - "pref_rc4" : True, - "prioritize_first_last_pieces" : False, - "web_proxy": 0, - "web_proxy_type" : common.ProxyType.none, - "peer_proxy_type" : common.ProxyType.none, - "dht_proxy_type" : common.ProxyType.none, - "tracker_proxy_type" : common.ProxyType.none, - "peer_proxy" : False, - "tracker_proxy" : False, - "dht_proxy" : False, - "peer_proxy_hostname" : "", - "peer_proxy_username" : "", - "peer_proxy_password" : "", - "peer_proxy_port": 8080, - "dht_proxy_hostname" : "", - "dht_proxy_username" : "", - "dht_proxy_password" : "", - "dht_proxy_port": 8080, - "web_proxy_hostname" : "", - "web_proxy_username" : "", - "web_proxy_password" : "", - "web_proxy_port": 8080, - "tracker_proxy_hostname" : "", - "tracker_proxy_username" : "", - "tracker_proxy_password" : "", - "tracker_proxy_port": 8080, - "queue_seeds_to_bottom" : False, - "random_port" : False, - "show_availability" : True, - "show_dl" : True, - "show_eta" : True, - "show_infopane" : True, - "show_peers" : True, - "show_seeders" : True, - "show_share" : True, - "show_size" : True, - "show_status" : True, - "show_toolbar" : True, - "show_ul" : True, - "start_in_tray" : False, - "tray_downloadspeedlist" : [5.0, 10.0, 30.0, 80.0, 300.0], - "tray_passwd" : "", - "tray_uploadspeedlist" : [5.0, 10.0, 30.0, 80.0, 300.0], - "use_compact_storage" : False, - "use_default_dir" : False, - "use_natpmp" : False, - "use_upnp" : False, - "use_lsd" : False, - "use_utpex" : True, - "window_height" : 480, - "new_releases" : True, - "window_maximized" : False, - "window_pane_position" : -1, - "window_width" : 640, - "window_x_pos" : 0, - "window_y_pos" : 0, - "availability_width" : -1, - "queue_width" : -1, - "name_width" : -1, - "dl_width" : -1, - "ul_width" : -1, - "eta_width" : -1, - "peer_width" : -1, - "seed_width" : -1, - "share_width" : -1, - "size_width" : -1, - "status_width" : -1, - "filename_f_width" : -1, - "size_f_width" : -1, - "priority_f_width" : -1, - "start_paused": False, - "use_advanced_bar" : True -} -else: - DEFAULT_PREFS = { - "enabled_plugins" : "Torrent Files:Torrent Peers:Torrent Notification", - "file_manager" : common.FileManager.xdg, - "open_folder_stock" : True, - "send_redund" : False, - "autoload" : False, - "open_folder_location": "", - "send_info" : True, - "auto_end_seeding" : False, - "auto_time_end_seeding" : False, - "new_releases" : True, - "auto_seed_ratio" : 0, - "auto_seed_time" : 0, - "close_to_tray" : False, - "enable_files_dialog" : False, - "enable_multi_only" : True, - "queue_above_completed" : False, - "clear_max_ratio_torrents" : False, - "clear_max_time_torrents" : False, - "default_autoload_path" : os.path.expanduser("~"), - "default_torrent_path" : os.path.join(common.CONFIG_DIR, 'torrentfiles'), - "default_download_path" : os.path.expanduser("~"), - "open_torrent_dialog_path" : os.path.expanduser("~"), - "choose_directory_dialog_path": os.path.expanduser("~"), - "enable_dht" : True, - "enable_system_tray" : True, - "enabled_plugins" : "Torrent Files:Torrent Peers", - "encin_state" : common.EncState.enabled, - "encout_state" : common.EncState.enabled, - "enclevel_type" : common.EncLevel.both, - "end_seed_ratio" : 0.0, - "gui_update_interval" : 1.0, - "listen_on" : [6881,6889], - "lock_tray" : False, - "max_half_open" : 20, - "connection_speed" : -1, - "max_active_torrents" : 8, - "max_active_torrents_tmp" : 8, - "max_connections_global" : 200, - "max_connections_per_torrent" : -1, - "max_download_speed" : -1, - "max_download_speed_bps": -1, - "max_upload_slots_global" : 4, - "max_upload_slots_per_torrent" : -1, - "max_upload_speed" : -1, - "max_upload_speed_bps" : -1, - "pref_rc4" : True, - "prioritize_first_last_pieces" : False, - "web_proxy": 0, - "web_proxy_type" : common.ProxyType.none, - "peer_proxy_type" : common.ProxyType.none, - "dht_proxy_type" : common.ProxyType.none, - "tracker_proxy_type" : common.ProxyType.none, - "peer_proxy" : False, - "tracker_proxy" : False, - "dht_proxy" : False, - "peer_proxy_hostname" : "", - "peer_proxy_username" : "", - "peer_proxy_password" : "", - "peer_proxy_port": 8080, - "dht_proxy_hostname" : "", - "dht_proxy_username" : "", - "dht_proxy_password" : "", - "dht_proxy_port": 8080, - "web_proxy_hostname" : "", - "web_proxy_username" : "", - "web_proxy_password" : "", - "web_proxy_port": 8080, - "tracker_proxy_hostname" : "", - "tracker_proxy_username" : "", - "tracker_proxy_password" : "", - "tracker_proxy_port": 8080, - "queue_seeds_to_bottom" : False, - "random_port" : False, - "show_availability" : True, - "show_dl" : True, - "show_eta" : True, - "show_infopane" : True, - "show_peers" : True, - "show_seeders" : True, - "show_share" : True, - "show_size" : True, - "show_status" : True, - "show_toolbar" : True, - "show_ul" : True, - "start_in_tray" : False, - "tray_downloadspeedlist" : [5.0, 10.0, 30.0, 80.0, 300.0], - "tray_passwd" : "", - "tray_uploadspeedlist" : [5.0, 10.0, 30.0, 80.0, 300.0], - "use_compact_storage" : False, - "use_default_dir" : False, - "use_natpmp" : False, - "use_upnp" : False, - "use_lsd" : False, - "use_utpex" : True, - "window_height" : 480, - "window_maximized" : False, - "window_pane_position" : -1, - "window_width" : 640, - "window_x_pos" : 0, - "window_y_pos" : 0, - "availability_width" : -1, - "queue_width" : -1, - "name_width" : -1, - "dl_width" : -1, - "ul_width" : -1, - "eta_width" : -1, - "peer_width" : -1, - "seed_width" : -1, - "share_width" : -1, - "size_width" : -1, - "status_width" : -1, - "filename_f_width" : -1, - "size_f_width" : -1, - "priority_f_width" : -1, - "start_paused": False, - "use_advanced_bar" : True -} - -class Preferences: - def __init__(self, filename=None, global_defaults=True, defaults=None): - self.mapping = {} - if defaults is not None: - for key in defaults.keys(): - self.mapping.setdefault(key, defaults[key]) - - if global_defaults is True: - self.mapping = DEFAULT_PREFS - - self.config_file = filename - if self.config_file is not None: - self.load(self.config_file) - self.change_hooks=[] - - # Allows you to access an item in a Preferences objecy by calling - # instance[key] rather than instance.get(key). However, this will - # return the value as the type it is currently in memory, so it is - # advisable to use get() if you need the value converted. - def __getitem__(self, key): - return self.mapping[key] - - def onValueChanged(self,value,method): - self.change_hooks.append([value,method]) - - def __setitem__(self, key, value): - if key not in self.mapping or self.mapping[key]!=value: - self.mapping[key] = value - for hook in self.change_hooks: - if (hook[0]==key): hook[1]() - - def __delitem__(self, key): - del self.mapping[key] - - def __len__(self): - return len(self.mapping) - - def has_key(self, key): return self.mapping.has_key(key) - def items(self): return self.mapping.items() - def keys(self): return self.mapping.keys() - def values(self): return self.mapping.values() - - def save(self, filename=None): - if filename is None: - filename = self.config_file - try: - pkl_file = open(filename, 'wb') - pickle.dump(self.mapping, pkl_file) - pkl_file.close() - except IOError: - pass - - def load(self, filename=None): - if filename is None: - filename = self.config_file - try: - pkl_file = open(filename, 'rb') - self.dump = pickle.load(pkl_file) - self.mapping.update(self.dump) - pkl_file.close() - except IOError: - pass - except EOFError: - pkl_file.close() - pass - - def set(self, key, value): - self[key] = value - - def get(self, key): - try: - value = self.mapping[key] - return value - except KeyError: - return None - - def remove(self, key): - self.mapping.pop(key) - - def clear(self): - self.mapping.clear() - - def printout(self): - for key in self.mapping.keys(): - print key, ':', self.mapping[key] diff --git a/src/tab_details.py b/src/tab_details.py deleted file mode 100644 index 7cf0c338f..000000000 --- a/src/tab_details.py +++ /dev/null @@ -1,201 +0,0 @@ -# -*- coding: utf-8 -*- -# -# tab_details.py -# -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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. - -import common -import gtk - -class DetailsTabManager(object): - def __init__(self, glade, manager): - self.manager = manager - - self.paused_unique_id = None - - # Look into glade's widget prefix function - self.progress_bar = glade.get_widget("progressbar") - self.custom_progress = glade.get_widget("custom_progress") - self.custom_progress.connect("expose_event", self.paint_customprogress) - self.name = glade.get_widget("summary_name") - self.total_size = glade.get_widget("summary_total_size") - self.num_files = glade.get_widget("summary_num_files") - self.pieces = glade.get_widget("summary_pieces") - self.availability = glade.get_widget("summary_availability") - self.total_downloaded = glade.get_widget("summary_total_downloaded") - self.total_uploaded = glade.get_widget("summary_total_uploaded") - self.download_speed = glade.get_widget("summary_download_speed") - self.upload_speed = glade.get_widget("summary_upload_speed") - self.seeders = glade.get_widget("summary_seeders") - self.peers = glade.get_widget("summary_peers") - self.percentage_done = glade.get_widget("summary_percentage_done") - self.share_ratio = glade.get_widget("summary_share_ratio") - self.tracker = glade.get_widget("summary_tracker") - self.tracker_status = glade.get_widget("summary_tracker_status") - self.next_announce = glade.get_widget("summary_next_announce") - self.eta = glade.get_widget("summary_eta") - self.torrent_path = glade.get_widget("summary_torrent_path") - self.advanced_progressbar = glade.get_widget("advanced_progressbar") - self.last_state = None - self.prefchanged_progress() - self.manager.config.onValueChanged('use_advanced_bar',self.prefchanged_progress) - - def prefchanged_progress(self): - self.use_advanced_bar=self.manager.config.get("use_advanced_bar") - if self.use_advanced_bar: - self.progress_bar.hide() - self.advanced_progressbar.show() - else: - self.progress_bar.show() - self.advanced_progressbar.hide() - - def paint_customprogress(self, arg1=None, arg2=None): - # Draw the custom progress bar - progress_window = self.custom_progress.window - colormap = self.custom_progress.get_colormap() - gc = progress_window.new_gc() - size = progress_window.get_size() - progress_window.begin_paint_rect(gtk.gdk.Rectangle(0, 0, size[0], size[1])) - height = size[1] - if height > 25: height = 25 - top = (size[1] - height) / 2 - gc.set_foreground(colormap.alloc_color('#F0F0FF')) - progress_window.draw_rectangle(gc, True, 0, top, size[0], height - 1) - gc.set_foreground(colormap.alloc_color('#A0A0AF')) - progress_window.draw_line(gc, 0, top + 4, size[0], top + 4) - state = self.last_state - if state != None: - gc.set_foreground(colormap.alloc_color('#2020FF')) - progress_window.draw_rectangle(gc, True, 0, top, int(size[0] * state['progress']), 4) - if state["total_wanted"] < state["piece_length"] and state["total_wanted"] > 0: - num_pieces = 1 - else: - num_pieces = state["total_wanted"] / state["piece_length"] - if num_pieces > 0: - for pieces_range in state['pieces']: - range_first = pieces_range[0] * size[0] / num_pieces - range_length = ((pieces_range[1] - pieces_range[0] + 1) * size[0] / num_pieces) - if range_length == 0: - range_length = 1 - gc.set_foreground(colormap.alloc_color('#8080FF')) - else: - gc.set_foreground(colormap.alloc_color('#2020FF')) - progress_window.draw_rectangle(gc, True, range_first, top + 5, range_length, height - 5) - gc.set_foreground(colormap.alloc_color('dim gray')) - progress_window.draw_line(gc, 0, top, 0, top + height) - progress_window.draw_line(gc, 0, top, size[0], top) - gc.set_foreground(colormap.alloc_color('white')) - progress_window.draw_line(gc, 0, top + height, size[0] - 1, top + height) - progress_window.draw_line(gc, size[0] - 1, top, size[0] - 1, top + height) - progress_window.end_paint() - # Done drawing custom progress bar - - def update(self, unique_id): - state = self.manager.get_torrent_state(unique_id) - - # Update selected files size, tracker, tracker status and next - # announce no matter what status of the torrent is - self.total_size.set_text(common.fsize(state["total_wanted"])) - self.tracker.set_text(str(state["tracker"])) - # At this time we still may not receive EVENT_TRACKER so there - # could be no tracker_status yet. - if "tracker_status" in state: - self.tracker_status.set_text(state["tracker_status"]) - self.next_announce.set_text(str(state["next_announce"])) - - if state['is_paused']: - if not self.paused_unique_id: - # Selected torrent just paused, zero data now and don't - # update it anymore on each update() - state['num_seeds'] = state['total_seeds'] = \ - state['num_peers'] = state['total_peers'] = \ - state['download_rate'] = state['upload_rate'] = 0 - - self.paused_unique_id = unique_id - elif self.paused_unique_id != unique_id: - # User selected another paused torrent with unique_id after - # paused torrent with self.paused_unique_id, so update - # currently selected unique_id and do full update of details - self.paused_unique_id = unique_id - else: - # If we already updated paused torrent - do nothing more - return - else: - self.paused_unique_id = None - - self.name.set_text(state['name']) - self.num_files.set_text(str(state['num_files'])) - self.pieces.set_text('%s x %s' % (state["num_pieces"], - common.fsize(state["piece_length"]))) - self.availability.set_text('%.3f' % state["distributed_copies"]) - self.total_downloaded.set_text('%s (%s)' % \ - (common.fsize(state["total_done"]), - common.fsize(state["total_payload_download"]))) - self.total_uploaded.set_text('%s (%s)' % \ - (common.fsize(self.manager.unique_IDs[unique_id].uploaded_memory+\ - state["total_payload_upload"]), - common.fsize(state["total_payload_upload"]))) - self.download_speed.set_text(common.fspeed(state["download_rate"])) - self.upload_speed.set_text(common.fspeed(state["upload_rate"])) - self.seeders.set_text(common.fseed(state)) - self.peers.set_text(common.fpeer(state)) - self.last_state=state - if self.use_advanced_bar: - self.paint_customprogress() - else: - self.progress_bar.set_fraction(float(state['progress'])) - self.progress_bar.set_text(common.fpcnt(state["progress"])) - self.eta.set_text(common.estimate_eta(state)) - self.share_ratio.set_text( '%.3f' % self.manager.calc_ratio(unique_id, - state)) - self.torrent_path.set_text(self.manager.get_torrent_path(unique_id)) - - def clear(self): - self.name.set_text("") - self.total_size.set_text("") - self.num_files.set_text("") - self.pieces.set_text("") - self.availability.set_text("") - self.total_downloaded.set_text("") - self.total_uploaded.set_text("") - self.download_speed.set_text("") - self.upload_speed.set_text("") - self.seeders.set_text("") - self.peers.set_text("") - self.progress_bar.set_fraction(0.0) - self.progress_bar.set_text("") - self.share_ratio.set_text("") - self.tracker.set_text("") - self.tracker_status.set_text("") - self.next_announce.set_text("") - self.eta.set_text("") - self.torrent_path.set_text("") - if self.use_advanced_bar: - self.last_state = None - self.paint_customprogress() diff --git a/src/wizard.py b/src/wizard.py deleted file mode 100644 index b93f5b16e..000000000 --- a/src/wizard.py +++ /dev/null @@ -1,332 +0,0 @@ -""" -this is our wizard which aids configuration for new users -""" -# -*- coding: utf-8 -*- -# -# Copyright (C) Marcos Pinto 2007 -# -# 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 2, 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. - - -class WizardGTK: - - """ - the main window for our configuration wizard - """ - - def __init__(self): - import gtk - import gtk.glade - import os - import deluge - import deluge.common - import deluge.pref - - self.wtree = gtk.glade.XML(deluge.common.get_glade_file("wizard.glade")\ - , domain='deluge') - self.wtree.signal_autoconnect({'apply_prefs': self.apply_prefs, - 'cancel': self.cancel, - 'toggle': self.toggle, - 'close': self.cancel}) - #add deluge logo to headers - self.window = self.wtree.get_widget("wizard") - self.manager = deluge.core - self.window.set_icon(deluge.common.get_logo(18)) - pixmap = deluge.common.get_logo(48) - self.window.set_page_header_image(self.wtree.get_widget('label1'), \ - pixmap) - self.window.set_page_header_image(self.wtree.get_widget('vbox1'), \ - pixmap) - self.window.set_page_header_image(self.wtree.get_widget('vbox2'), \ - pixmap) - self.window.set_page_header_image(self.wtree.get_widget('vbox3'), \ - pixmap) - self.window.set_page_header_image(self.wtree.get_widget\ - ('chk_send_info'), pixmap) - - #activate forward buttons for all pages - self.window.set_page_complete(self.wtree.get_widget('label1'), True) - self.window.set_page_complete(self.wtree.get_widget('vbox1'), True) - self.window.set_page_complete(self.wtree.get_widget('vbox2'), True) - self.window.set_page_complete(self.wtree.get_widget('vbox3'), True) - self.window.set_page_complete(self.wtree.get_widget('chk_send_info'), \ - True) - if not os.path.exists(deluge.common.CONFIG_DIR): - os.makedirs(deluge.common.CONFIG_DIR) - config_file = deluge.common.CONFIG_DIR + "/prefs.state" - self.config = deluge.pref.Preferences(config_file, False, - defaults={"listen_on" : [6881,6889], - "send_info": True, - "random_port": False, - "max_half_open" : 8, - "max_active_torrents" : 8, - "max_upload_slots_global" : 15, - "max_connections_global" : 200, - "max_upload_speed" : -1, - "default_download_path" : os.path.expanduser("~/"), - "use_default_dir" : False - }) - try: - self.config.load() - except IOError: - pass - else: - self.wtree.get_widget('spin_port_min').set_value(self.config.\ - get("listen_on")[0]) - self.wtree.get_widget('spin_port_max').set_value(self.config.\ - get("listen_on")[1]) - self.wtree.get_widget('chk_send_info').set_active(self.config.\ - get("send_info")) - self.wtree.get_widget('chk_random_ports').set_active(self.config.\ - get("random_port")) - self.wtree.get_widget('radio_save_all_to').set_active(self.config.\ - get("use_default_dir")) - self.wtree.get_widget('download_path_button').set_filename(self.\ - config.get("default_download_path")) - self.wtree.get_widget('spin_max_connections_global').set_value(\ - self.config.get("max_connections_global")) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - self.config.get("max_upload_slots_global")) - self.wtree.get_widget('spin_max_upload').set_value(self.config.\ - get("max_upload_speed")) - self.wtree.get_widget('spin_torrents').set_value(self.config.\ - get("max_active_torrents")) - self.wtree.get_widget('spin_max_half_open').set_value(self.config.\ - get("max_half_open")) - - #show wizard - self.window.show() - gtk.main() - - def toggle(self, *args): - """ - updates the gui with preferences according to user input - """ - self.wtree.get_widget('spin_port_min').set_sensitive( - not self.wtree.get_widget('chk_random_ports').get_active()) - self.wtree.get_widget('spin_port_max').set_sensitive( - not self.wtree.get_widget('chk_random_ports').get_active()) - if self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "28k": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('25')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('1')) - self.wtree.get_widget('spin_max_upload').set_value(float('2')) - self.wtree.get_widget('spin_torrents').set_value(float('1')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "56k": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('30')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('3')) - self.wtree.get_widget('spin_max_upload').set_value(float('2')) - self.wtree.get_widget('spin_torrents').set_value(float('1')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "64k": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('75')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('2')) - self.wtree.get_widget('spin_max_upload').set_value(float('5')) - self.wtree.get_widget('spin_torrents').set_value(float('1')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "96k": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('75')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('3')) - self.wtree.get_widget('spin_max_upload').set_value(float('7')) - self.wtree.get_widget('spin_torrents').set_value(float('1')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "128k": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('88')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('3')) - self.wtree.get_widget('spin_max_upload').set_value(float('9')) - self.wtree.get_widget('spin_torrents').set_value(float('1')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "192k": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('90')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('3')) - self.wtree.get_widget('spin_max_upload').set_value(float('17')) - self.wtree.get_widget('spin_torrents').set_value(float('1')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "256k": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('130')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('3')) - self.wtree.get_widget('spin_max_upload').set_value(float('22')) - self.wtree.get_widget('spin_torrents').set_value(float('1')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "384k": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('230')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('4')) - self.wtree.get_widget('spin_max_upload').set_value(float('35')) - self.wtree.get_widget('spin_torrents').set_value(float('3')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "512k": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('250')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('4')) - self.wtree.get_widget('spin_max_upload').set_value(float('47')) - self.wtree.get_widget('spin_torrents').set_value(float('3')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "640k": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('375')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('4')) - self.wtree.get_widget('spin_max_upload').set_value(float('60')) - self.wtree.get_widget('spin_torrents').set_value(float('4')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "768k": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('450')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('5')) - self.wtree.get_widget('spin_max_upload').set_value(float('72')) - self.wtree.get_widget('spin_torrents').set_value(float('5')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "1Mbit": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('600')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('6')) - self.wtree.get_widget('spin_max_upload').set_value(float('92')) - self.wtree.get_widget('spin_torrents').set_value(float('5')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "2Mbit": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('750')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('8')) - self.wtree.get_widget('spin_max_upload').set_value(float('186')) - self.wtree.get_widget('spin_torrents').set_value(float('9')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "10Mbit": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('800')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('25')) - self.wtree.get_widget('spin_max_upload').set_value(float('1120')) - self.wtree.get_widget('spin_torrents').set_value(float('15')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "20Mbit": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('850')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('30')) - self.wtree.get_widget('spin_max_upload').set_value(float('2240')) - self.wtree.get_widget('spin_torrents').set_value(float('15')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "40Mbit": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('900')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('35')) - self.wtree.get_widget('spin_max_upload').set_value(float('4480')) - self.wtree.get_widget('spin_torrents').set_value(float('15')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "50Mbit": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('950')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('50')) - self.wtree.get_widget('spin_max_upload').set_value(float('5600')) - self.wtree.get_widget('spin_torrents').set_value(float('20')) - elif self.wtree.get_widget('combo_upload_line').get_active_text() == \ - "100Mbit": - self.wtree.get_widget('spin_max_connections_global').set_value(\ - float('1000')) - self.wtree.get_widget('spin_max_upload_slots_global').set_value(\ - float('50')) - self.wtree.get_widget('spin_max_upload').set_value(float('11200')) - self.wtree.get_widget('spin_torrents').set_value(float('25')) - - def create_file(self): - """ - creates file that we check for to know if we need to run the wizard or - not - """ - import os - import deluge.common - if not os.path.exists(os.path.join(deluge.common.CONFIG_DIR, 'firstrun')): - try: - firstrun = open(os.path.join(deluge.common.CONFIG_DIR, 'firstrun'), 'w') - firstrun.write("") - firstrun.close() - except: - pass - - def cancel(self, *args): - """ - exits the wizard and creates file so we dont re-run - """ - import gtk - self.create_file() - self.window.destroy() - gtk.main_quit() - - def apply_prefs(self, *args): - """ - saves configuration settings - """ - import gtk - self.create_file() - self.config.set("random_port", self.wtree.get_widget('chk_random_ports'\ - ).get_active()) - self.config.set("send_info", self.wtree.get_widget("chk_send_info").\ - get_active()) - self.config.set("listen_on", [self.wtree.get_widget("spin_port_min")\ - .get_value(), self.wtree.get_widget("spin_port_max").get_value()]) - self.config.set("send_info", self.wtree.get_widget("chk_send_info").\ - get_active()) - self.config.set("max_connections_global", int(self.wtree.get_widget\ - ('spin_max_connections_global').get_value())) - self.config.set("max_upload_slots_global", int(self.wtree.get_widget\ - ('spin_max_upload_slots_global').get_value())) - self.config.set("max_upload_speed", int(self.wtree.get_widget(\ - 'spin_max_upload').get_value())) - self.config.set("max_active_torrents", int(self.wtree.get_widget(\ - 'spin_torrents').get_value())) - self.config.set("max_half_open", int(self.wtree.get_widget(\ - 'spin_max_half_open').get_value())) - self.config.set("use_default_dir", self.wtree.get_widget(\ - 'radio_save_all_to').get_active()) - self.config.set("default_download_path", self.wtree.get_widget(\ - 'download_path_button').get_filename()) - self.config.save() - - gtk.main_quit()